OpenVMS Source Code Demos
POPULATION_SIM_1008.BAS
1000 %title "population_sim_xxx.bas" !
%ident "version 100.8" ! <<<---+---
declare string constant k_version = "100.8" , ! <<<---+ &
k_program = "population_sim" !
!==============================================================================================================
! title : population_sim_100.bas
! author : Neil Rieck (https://neilrieck.net) (mailto:[email protected])
! purpose: A population study written for OpenVMS BASIC
! notes : 1) this is an idealized society with no disease, congenital birth defects or accidental deaths
! : 2) everyone makes it to old age and dies in the same year
! : 3) everyone mates in a controlled fashion (no rape or infidelity)
! : 4) selected group(s) mate and give birth all in the same year
! : 5) selected group(s) only mate with themselves
! : 6) this society starts with an even population distribution
! : 7) RESULT 1: if every two people only produce two children, population will remain constant
! : 8) RESULT 2: if every two people only reproduce once, the population will shrink slowly
! : 9) all logic (except teen_fraction) is implemented with integers. I did this to make this sim more
! deterministic.
! history:
! ver who when what
! --- --- ------ ----------------------------------------------------------------------------------------------
! 100 NSR 090722 1. original work
! NSR 090723 2. added a second array to capture tallies for cross-generational analysis
! NSR 090726 3. a few final tweaks and cosmetic changes
! 4. added experimental fraction mode
! NSR 090801 5. introduced some simplifications to help you to understand the operation of this sim (these
! changes will make the code less efficient but more understandable)
! NSR 090803 6. now early teenage matings always happen at age 15 (this will allow me to have teenage
! matings while the first planned mating is delayed)
! 7. added support for fractional planned reproduction
! NSR 100402 8. max age was increased from 100,000 to 20 million (so we can model the world)
! changed LONG integers to XFLOAT
! changed DOUUBLE floats to XFLOAT
!==============================================================================================================
OPTION type = explicit , ! no kid stuff &
constant type = decimal , ! &
size = (decimal(20,6), integer long ) !
!
set no prompt !
!
declare long constant k_teenage_mating_year = 15 !
!
! variable declarations
!
declare long x
declare decimal(20,0) ! &
max_age , ! maximum age &
repro_age , ! repro age &
repro_num , ! repro num &
repro_gap , ! repro gap &
age_group , ! age group &
age_group_size , ! "initial" age group size &
max_year , ! maximum years &
year , ! year counter &
total , ! &
limit , ! &
mating , ! &
calc , ! &
string dump$ , ! &
junk$ , ! &
decimal(20,6) float1 , ! &
float2 , ! &
float_temp , ! &
teen_fraction , ! &
planned_fraction !
!====================================================================================================
! main
!====================================================================================================
2000 main:
on error goto common_trap
!
print "======================================================================="
print k_program +"_"+ k_version !
print "======================================================================="
print "Note: Decimal input is only allowed on two inputs." !
print " All others require integers" !
print " Most inputs default to the higher numerical value" !
!
! prompt for maximum age
!
input "maximum age (years) ? (eg 75) ";junk$ !
when error in !
max_age = integer(junk$) !
use !
end when !
select max_age !
case 0 !
max_age = 75 ! set default
case < 25 !
max_age = 25 !
print "Note: 'maximum age' was increased to 25" !
case > 99 !
max_age = 99 !
print "Note: 'maximum age' was decreased to 99" !
end select !
!
! prompt for age group size
!
input "age group size ? (eg 13157895) ";junk$ !
when error in !
age_group_size = integer(junk$) !
use !
end when !
select age_group_size !
case 0 !
age_group_size = 13157895 ! set default
case < 100 !
age_group_size = 100 !
print "Note: 'age group size' was increased to "+ str$(age_group_size)
case > 20000000 ! 20 million
age_group_size = 20000000 !
print "Note: 'age group size' was decreased to "+ str$(age_group_size)
end select !
!
! prompt for "reproduction events"
!
input "planned reproduction events ? (eg 1) ";junk$ !
when error in !
repro_num = integer(junk$) !
use !
repro_num = 0 !
end when !
select repro_num !
case 0 !
repro_num = 1 ! set default
case < 0 !
repro_num = 0 !
print "Note: 'reproduction number' was increased to 0" !
case > 10 !
repro_num = 10 !
print "Note: 'reproduction number' was decreased to 10" !
end select !
!
! prompt for "reproduction fraction"
!
input "planned reproduction fraction? (eg 0.1 - 1.0) ";junk$ !
when error in !
planned_fraction = decimal(junk$) !
use !
planned_fraction = 0 !
end when !
select planned_fraction !
case 0 !
planned_fraction = 1.0 ! set default
case < 0.1 !
planned_fraction = 0.1 !
print "Note: 'planned reproduction fraction' was increased to "+ str$(planned_fraction)
case > 1.0 !
planned_fraction = 1.0 !
print "Note: 'planned reproduction fraction' was decreased to "+ str$(planned_fraction)
end select !
!
! prompt for "reproduction age"
!
if repro_num > 0 then ! if we're going to reproduce
input "reproduction age (years) ? (eg 20) ";repro_age !
limit = max_age -1 !
select repro_age !
case 0 !
repro_age = 20 !
case > limit !
repro_age = limit !
case < 20 !
repro_age = 20 !
print "Note: 'reproduction age' was increased to 20" !
end select !
end if !
!
if repro_num > 1 then ! if more than one reproduction...
input "reproduction gap (years) ? (eg 2) ";repro_gap !
select repro_gap !
case 0 !
repro_gap = 2 !
case > 10 !
repro_gap = 10 !
print "Note: 'reproduction gap' was decreased to 10" !
end select !
end if !
!
if repro_num > 0 then ! if at least one reproduction...
print "Notes:"
print " 1) this next step deals with early teenage reproduction"
print " 2) this calc will be applied to age group "+ str$(k_teenage_mating_year)
print " 3) the default is 0.0 (off)"
input "early teenage mating fraction? (eg 0.0 - 1.0) "; junk$ !
when error in !
teen_fraction = decimal(junk$) !
use !
teen_fraction = 0 !
end when !
select teen_fraction !
case < 0.0 !
teen_fraction = 0.0 !
print "Note: 'early teenage reproduction fraction' was increased to "+ str$(teen_fraction)
case > 1.0 !
teen_fraction = 1.0 !
print "Note: 'early teenage reproduction fraction' was decreased to "+ str$(teen_fraction)
end select !
end if !
!
! make sure we have enough space for x reproductions
!
! given: repro_num 3
! repro_age 20
! repro_gap 1
!
! then: repro-1 20
! repor-2 21
! repor-3 22
!
select repro_num !
case 0 ! no reproductions so no age limit
limit = 0 !
case 1 !
limit = repro_age !
case else !
limit = repro_age + (repro_gap * (repro_num-1)) !
end select !
if max_age <= limit then !
max_age = limit +1 !
print "Note: 'maximum age' was raised to "+str$(max_age) !
end if !
!
! make sure we have enough years to view all events
!
limit = max_age !
print "maximum years to model ? (eg "+ str$(limit)+") "; !
input max_year !
max_year = limit if max_year < limit !
!------------------------------------------------------------------------
! init population
!------------------------------------------------------------------------
3000 print "======================================================================="
print "Initializing population age groups <<<" !
dim decimal(20,0) gen(max_age) ! reserve space for various ages
dim string mode$(max_age) ! reserve space for reproduction modes
dim decimal(20,0) gen_sum(max_year) ! bf_100.2
for age_group = 0 to max_age ! people will have ages 0 to max_age
gen(age_group) = age_group_size ! start with x people in each age group
next age_group !
if repro_num > 0 then ! if one, or more, matings have been selected
for mating = 0 to repro_num-1 !
calc = repro_age + (mating * repro_gap) !
mode$(calc) = "PR" ! flag this year for planned reproduction
next mating !
if teen_fraction > 0.0 then !
calc = k_teenage_mating_year !
mode$(calc) = "TF" ! flag this year for early teenaged reproduction
end if !
end if !
gosub print_total_pop !
gosub dump_population_details !
!------------------------------------------------------------------------
! let time take it's toll as the years ripple past
!------------------------------------------------------------------------
4000 print "running the sim" !
for year = 1 to max_year ! cycle through the years
for age_group = (max_age-1) to 0 step -1 ! people age by one year (last group dies)
gen(age_group+1) = gen(age_group) ! people age one year
next age_group !
gen(0) = 0 ! zap age_group zero (babies)
for age_group = 0 to max_age !
select mode$(age_group) !
case "PR" ! W/hole R/eprodction
calc = repro_age + (mating * repro_gap) !
float_temp = gen(calc) !
float_temp = float_temp * planned_fraction / 2.0 !
gen(0) = gen(0) + float_temp !
case "TF" ! F/ractional R/eprodction
calc = k_teenage_mating_year !
float_temp = gen(calc) !
float_temp = float_temp * teen_fraction / 2.0 !
gen(0) = gen(0) + float_temp !
end select !
next age_group !
gosub print_total_pop !
gosub dump_population_details !
next year !
goto fini !
!------------------------------------------------------------------------
! print total population
!------------------------------------------------------------------------
5000 print_total_pop: !
total = 0 ! init
for age_group = 0 to max_age !
total = total + gen(age_group) !
next age_group !
gen_sum(year) = total ! record the total number of people here
print using "Year: ### Population size: ############"; year; total; !
if year < 1 then !
print !
else !
float2 = gen_sum(year) !
float1 = gen_sum(year-1) !
if float1 >= 0.0 then !
float2 = float2/float1 !
else !
float2 = 0.0 !
end if
print using " growth rate: ##.######", float2 !
end if !
return !
!------------------------------------------------------------------------
! dump population details by age group
!------------------------------------------------------------------------
6000 dump_population_details: !
select dump$ !
case "YA" ! Yes All
goto dump_population_details_start !
case "NA" ! No All
goto dump_population_details_exit !
end select !
!
get_dump_option: !
input "view population details ? (Y/N/YA/NA) ";dump$ !
dump$ = edit$(dump$,32+2) !
select dump$ !
case "" !
dump$ = "Y" !
case "Y","YA" ! Yes, Yes All
case "N","NA" ! No, No All
goto dump_population_details_exit !
case else !
print "bad input" !
goto get_dump_option !
end select !
!
! start dump
!
7000 dump_population_details_start:
print using "Detail Report for Year ###", year; !
if year = 0 then !
print " (after initialize)" !
else !
print " (after running one pass)" !
end if !
for age_group = 0 to max_age !
print using "######## members of age group: ### ";gen(age_group); age_group;
print "repro code: "; mode$(age_group); !
select mode$(age_group) !
case "PR" !
print " ("+ format$(planned_fraction,"#.######") +")" !
case "TF" !
print " ("+ format$(teen_fraction , "#.######") +")" !
case else !
print !
end select !
next age_group !
print "Legend: PR = Planned Reproduction. TR = Teenage Reproduction" !
print "----------------------------------------------------------------------"
!
dump_population_details_exit: !
return !
!------------------------------------------------------------------------
! adios
!------------------------------------------------------------------------
8000 fini: !
print "======================================================================="
Print "The simulation has ended <<<"
print "Results:"
print " starting population : "+ str$( gen_sum(0 ) ) !
print " ending population : "+ str$( gen_sum(year) ) !
float2 = gen_sum(year) !
float1 = gen_sum(0 ) !
if float1 >= 0.0 then !
float2 = float2/float1 !
else !
float2 = 0.0 !
end if !
junk$ = format$(float2, "########.######") !
print " total change : "+ edit$(junk$,2) !
print "Parameters:" !
print " maximum years to model : "+ str$( max_year ) !
print " maximum age : "+ str$( max_age ) !
print " age group size : "+ str$( age_group_size ) !
print " planned reproduction events : "+ str$( repro_num ) !
print " planned reproduction fraction: "+ format$(planned_fraction, "#.######")
print " planned reproduction rate p/p: "; !
junk$ = format$(planned_fraction * repro_num / 2.0, "##.######") !
junk$ = edit$(junk$,2) ! remove white space
print junk$ !
print " reproduction age : "+ str$( repro_age ) !
print " reproduction gap : "+ str$( repro_gap ) !
print " early teenage mating fraction: "+ format$(teen_fraction, "#.######");
if teen_fraction = 0.0 then !
print " (disabled)" !
else !
print !
end if !
goto adios
!------------------------------------------------------------------------
! common error trap
!------------------------------------------------------------------------
common_trap:
print
print "=== common trap ==="
print "error ";str$(err)
print "line ";str$(erl)
print "text ";ert$(err)
resume adios
!------------------------------------------------------------------------
! that's all folks
!------------------------------------------------------------------------
adios:
end !