Page 1 of 1

Mathematical model solver.

Posted: Mon May 18, 2015 2:44 pm
by Henko
It's not easy to explain what this little program does, but i'll give it a try.
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$)