When making a mathematical model of a physical, chemical, economical or whatever kind of proces or system, that model will consist of a number of state variables and a number of formulas (or equations) that give the relationships between these variables.
To clarify, an simple example will be used throughout this explanation, namely an annuity loan, which is used mostly for mortgages.
The system is then "annuity loan".
There are 5 variables :
the capital, the number of periods, the montly payment, the yearly interest rate, and the monthly interest rate.
There are 2 formulas:
1. calculation of the monthly interest rate as a function of the yearly interest rate using the compound interest formula. The yearly rate is the rate as given by the loan company, the monthly rate is used to calculate the monthly payment.
The formula is: m_rate = (1+y_rate)^(1/12) - 1
2. The annuity formula to calculate the monthly payment as function of the other variables.
The formula is: m_pay = m_rate/(1-(1+m_rate)^(-n_months))*capital
Example data and these 2 formulas (somewhat rewritten) are entered in the program in the yellow sections of the code. The two variables m_rate and m_pay are given guessed values.
After program start, the available formulas are displayed using buttons.
Selecting a formula by pressing the appropiate button will display the variables pertaining to that equation.
Values can be changed in the fields on the right side (don't forget to press the Enter key, otherwise the "field_changed" function will not be triggerd!). Pressing any of the buttons on the left side will calculate the value for that variable.
Advantages of this solution method are:
1. Formulas (equations) need be entered only once in the coding section, and any variable in that equation can be calculated, when the other values are valid.
2. The formulas may have any complexity.
3. Only the yellow sections have to be replaced to define an other model than the annuity loan.
Warning: the chosen solution method in the program (newton-raphson iteration) may not converge to a valid solution. But if the model is derived from an real proces or system, the algorithm will converge most of the time. Convergence is also dependent upon the quality of the initial (guessed) values of the variables who are to be calculated.
The output of the program fits on iPhones for little numbers of equations and variables, but could be further optimized for iPhones.
Code: Select all
' equations solver / system analyzer
' programmed by Henko in smartbasic, may 2015
' in yellow: specific data and coding for annuity example
'
option base 0
dim varname$(16),value(16),status(16)
dim equname$(6),equ(6,11)
graphics ! graphics clear ! draw color 0,0,0
read system_title$
read nequ,nvar
for i=1 to nequ
read equname$(i)
for j=0 to 4 ! read equ(i,j) ! next j
next i
for i=1 to nvar ! read varname$(i),value(i) ! next i
'y'
data "Annuity loan" ' system name
data 2,5 ' 2 equations and 5 variables
data "interest rates", 2, 2,5, 0,0 ' variables in first equation
data "annuity formula", 4, 1,5,3,4 ' variables in second equation
data "Capital",125000 ' name and initial value of first variable
data "int.rate / yr",0.06 ' same for second variable
data "# months",360 ' third variable
data "pay/month",500 ' fourth variable
data "int.rate/month",.005 ' fifth variable
''
y_eq=10 ! y_var=y_eq+50*nequ+20 ! old_equ=0
draw font size 30 ! draw text system_title$ at 50,10 ! draw font size 20
equ_disp()
loop: slowdown
for i=1 to nequ ! if bp("eq" & i) then cur_equ=i ! next i
if cur_equ <> old_equ then
if old_equ>0 then var_del(old_equ)
var_disp(cur_equ) ! old_equ=cur_equ
end if
for i=1 to equ(cur_equ,0)
fn$="var" & i
if field_changed(fn$) then
value(equ(cur_equ,i))=field_text$(fn$) ! break
end if
if bp(fn$) then field fn$ text solve(value,equ,cur_equ,i)
next i
goto loop
end
def equi(value(),equ(,),nre) ' coding the equations
'y'
on nre goto eq1,eq2
eq1: ' relation between yearly interest rate and the monthly rate
return (1+value(equ(nre,1)))^(1/12)-1-value(equ(nre,2))
eq2: ' annuity formula
result=1-(1+value(equ(nre,2)))^(-value(equ(nre,3)))
result=value(equ(nre,2))/result*value(equ(nre,1))-value(equ(nre,4))
return result
''
end def
def equ_disp ' display equation buttons
for i=1 to .nequ
button "eq" & i text .equname$(i) at 10,.y_eq+50*i size 300,30
next i
end def
def var_disp(nr) ' display variable name-buttons and value-fields
for i=1 to .equ(nr,0)
button "var" & i text .varname$(.equ(nr,i)) at 10,.y_var+50*i size 150,30
field "var" & i text .value(.equ(nr,i)) at 170,.y_var+50*i size 140,30
next i
end def
def var_del(nr) ' remove variable buttons and fields
for i=1 to .equ(nr,0)
button "var" & i delete ! field "var" & i delete
next i
end def
def solve(value(),equ(,),nre,nrv) ' newton-raphson iteration
imax=10 ! eps=.001
for i=1 to imax
delta=equi(value,equ,nre)/deriv(value,equ,nre,nrv)
value(equ(nre,nrv))-=delta
if abs(delta)<eps then return value(equ(nre,nrv))
next i
return -999
end def
def deriv(value(),equ(,),nre,nrv) ' partial derivate of nre w.r.t. nrv
fx=equi(value,equ,nre) ! dx=.001*value(equ(nre,nrv))
value(equ(nre,nrv))+=dx
fxplus=equi(value,equ,nre)
value(equ(nre,nrv))-=dx
return (fxplus-fx)/dx
end def
def bp(b$) = button_pressed(b$)