Fortran Program Crashes when running - crash

I'm a starter in Fortran, using it to solve mathematical models in economics.
I wrote a program (below) that is crashing when running. Windows show that message of error and nothing seems to happen. I haven't got a clue of what may be wrong, I already debugged it and it does not show any error message on the build log.
I am using gfortran.
!Value function iteration program with matrices, based on the matlab similar code
program valuefuncmat
implicit none
integer,parameter::dp=selected_real_kind(15) !double precision
integer,parameter::lower=0,upper=50 !lower and upper bounds on capital grid (lower = b in the model)
real(dp),parameter::hex1=.01,hex2=.1 !steps on capital grid, finer on low levels of capital
integer::i,j !loop counters
integer,parameter::sze1=((15-lower)/hex1)+1,sze2=( ((upper-15)/hex2)+1)
integer,parameter::sze=sze1+sze2
real(dp)::alinha1(sze1),alinha2(sze2),agrid(sze)
11 format(i5)
12 format(f35.10)
interface !interface of the functions used
function kron(A,B)
implicit none
integer,parameter::dp=selected_real_kind(15) !double precision
real(dp),dimension(:,:), intent(in)::A,B !dummy arguments
real(dp),dimension(size(A,1)*size(B,1),size(A,2)*size(B,2))::kron
end function kron
function repvec(A,n)
implicit none
integer,parameter::dp=selected_real_kind(15) !double precision, not essencial in the code
real(dp),dimension(:), intent(in)::A
integer::n
real(dp),dimension(n,size(A))::repvec
end function repvec
function repmat(A,n)
implicit none
integer,parameter::dp=selected_real_kind(15) !double precision, not essencial in the code
real(dp),dimension(:,:), intent(in)::A
integer::n
real(dp),dimension(size(A)*n,size(A))::repmat
end function repmat
function kronvec(A,V)
implicit none
integer,parameter::dp=selected_real_kind(15) !double precision, not essencial in the code
real(dp),dimension(:,:),intent(in)::A
integer,dimension(:),intent(in)::V
real(dp),dimension(size(A,1)*size(V),size(A,2))::kronvec
end function kronvec
function kronvec2(A,V)
implicit none
integer,parameter::dp=selected_real_kind(15) !double precision, not essencial in the code
integer,dimension(:,:),intent(in)::A
real(dp),dimension(:),intent(in)::V
real(dp),dimension(size(A,1)*size(V),size(A,2))::kronvec2
end function kronvec2
end interface
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!Markov Matrix and Productivity Grid!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
real(dp), dimension(3,3), parameter::P=reshape((/ .91,.08,.01,.13,.82,.05,.005,.07,.925 /),(/3,3/),(/.0/),(/2,1/)) !markov matrix
real(dp), dimension(3), parameter::theta_grid=(/ .1,.5,1.0 /) !the grid of productivity
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
real(dp),parameter::A=1.0,alpha=.25,beta=.98 !Parameters of Functional Forms
real(dp),parameter::r=0.05,w=1.0,T=1.0 !Parameters for testing the value function iteration
integer,parameter::y=1
real(dp),dimension(size(theta_grid),size(agrid))::vIN=.0,vOUT=1.0,apol
real(dp)::transf(size(theta_grid)*size(agrid),size(agrid)),amatrix(size(agrid),size(agrid))
real(dp)::C(size(agrid)*size(theta_grid),size(agrid))
real(dp)::Rzao(size(agrid)*size(theta_grid),size(agrid)),tvOUT(size(theta_grid)*size(agrid))
integer::indexa(size(theta_grid)*size(agrid)),um(size(agrid))=1,onesm(size(theta_grid))=1,umzao(size(agrid),size(agrid))=1
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!initializing the capital grid!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
do i=1,sze1
alinha1(i)=lower+(i-1)*hex1
end do
do i=1,sze2
alinha2(i)=alinha1((sze1))+hex2 +(i-1)*hex2
end do
agrid(:sze1)=alinha1
agrid(sze1+1:sze)=alinha2
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!Beginning the actual value function iteration algorithm!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
transf(1:y*size(agrid),:)=T !defining the types that will receive the transfer
Amatrix=transpose(repvec((1+r)*agrid,size(agrid)))-repvec(agrid,size(agrid)) !every combination of a and a' on square matrix of rank equal to the size of agrid
C=repmat(Amatrix,size(theta_grid))+w*kronvec2(umzao,theta_grid)+transf
where (C<=0) C=0.00000000000000001
Rzao=log(C)
do while (maxval(abs(vIN-vOUT))>0.001)
vIN=vOUT
tvOUT=maxval(Rzao+beta*matmul(kronvec(P,um),vIN),dim=2)
indexa=maxloc(Rzao+beta*matmul(kronvec(P,um),vIN),dim=2)
vOUT=reshape(tvOUT,(/size(theta_grid),size(agrid)/),order=(/2,1/))
end do
do i=1,size(vOUT,1)
write(*,'(20G12.4)'),vOUT(i,:)
end do
end program
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!Kronecker Product Routine!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
function kron(A,B)
implicit none
integer,parameter::dp=selected_real_kind(15) !double precision, not essencial in the code
real(dp),dimension(:,:), intent(in)::A,B !dummy arguments
real(dp),dimension(size(A,1)*size(B,1),size(A,2)*size(B,2))::kron !output matrix of the kronecker product
integer::i,j !loop counters
do i=1,size(A,1)
do j=1,size(A,2)
kron(1+size(B,1)*(i-1):size(B,1)+size(B,1)*(i-1),1+size(B,2)*(j-1):size(B,2)+size(B,2)*(j-1))=A(i,j)*B
end do
end do
end function kron
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!Function that calculates a kronecker product between a matrix and a vector!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Vector must be integer!!!!!!!!!!!!!!!!!!!!!!!!!!!
function kronvec(A,V)
implicit none
integer,parameter::dp=selected_real_kind(15) !double precision, not essencial in the code
real(dp),dimension(:,:),intent(in)::A
integer,dimension(:),intent(in)::V
real(dp),dimension(size(A,1)*size(V),size(A,2))::kronvec
integer::i
do i=1,size(V)
kronvec(1+size(A,1)*(i-1):size(A,1)+size(A,1)*(i-1),:)=A*V(i)
end do
end function kronvec
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!Function that calculates a kronecker product between a matrix and a vector!!!!
!!!!!!!!!!!!!!!Matrix must be integer and vector real!!!!!!!!!!!!!!!!!!!!!!!!!!!
function kronvec2(A,V)
implicit none
integer,parameter::dp=selected_real_kind(15) !double precision, not essencial in the code
integer,dimension(:,:),intent(in)::A
real(dp),dimension(:),intent(in)::V
real(dp),dimension(size(A,1)*size(V),size(A,2))::kronvec2
integer::i
do i=1,size(V)
kronvec2(1+size(A,1)*(i-1):size(A,1)+size(A,1)*(i-1),:)=A*V(i)
end do
end function kronvec2
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!Function that repeats a vector n times verticaly!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
function repvec(A,n)
implicit none
integer,parameter::dp=selected_real_kind(15) !double precision, not essencial in the code
real(dp),dimension(:), intent(in)::A
integer::n
real(dp),dimension(n,size(A))::repvec
integer::i
do i=1,n
repvec(i,:)=A
end do
end function repvec
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!Function that repeats a matrix n times verticaly!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
function repmat(A,n)
implicit none
integer,parameter::dp=selected_real_kind(15) !double precision, not essencial in the code
real(dp),dimension(:,:), intent(in)::A
integer::n
real(dp),dimension(size(A)*n,size(A))::repmat
integer::i
do i=1,size(A)
repmat(1+size(A)*(i-1):size(A)+size(A)*(i-1),:)=A
end do
end function repmat

I ran your code through the NAG Fortran Compiler (on Linux). The version you have posted doesn't compile for me:
> nagfor -mtrace=all -u -C=all -C=undefined valuefuncmat.f90
...
Error: valuefuncmat.f90, line 100: Syntax error
detected at )#,
...
That of course is easy to rectify (i.e., change line 100 to write(*,'(20G12.4)') vOUT(i,:)).
With that done, recompiling and running reveals
> nagfor -mtrace=all -u -C=all -C=undefined valuefuncmat.f90 && ./a.out
NAG Fortran Compiler Release 6.0(Hibiya) Build 1050
Extension: valuefuncmat.f90, line 88: Line longer than 132 characters
Warning: valuefuncmat.f90, line 104: Unused local variable APOL
Questionable: valuefuncmat.f90, line 104: Variable INDEXA set but never referenced
Warning: valuefuncmat.f90, line 104: Unused local variable J
Warning: valuefuncmat.f90, line 104: Unused interface for procedure KRON
Warning: valuefuncmat.f90, line 104: Local variable ONESM is initialised but never used
Warning: valuefuncmat.f90, line 62: Unused PARAMETER A
Warning: valuefuncmat.f90, line 62: Unused PARAMETER ALPHA
[NAG Fortran Compiler normal termination, 8 warnings]
[Allocated item 1 (size 65537) = Z'2AE913113010']
[Allocated item 2 (size 65537) = Z'2AE913123030']
[Allocated item 3 (size 65537) = Z'2AE913133050']
[Allocated item 4 (size 14808) at line 88 of valuefuncmat.f90 = Z'2AE913143070']
[Allocated item 5 (size 27409608) at line 154 of valuefuncmat.f90 = Z'2AE913413010']
[Allocated item 6 (size 27409608) at line 154 of valuefuncmat.f90 = Z'2AE914E37010']
[Deallocated item 6 (size 27409608, at Z'2AE914E37010') at line 166 of valuefuncmat.f90]
[Allocated item 7 (size 27409608) at line 154 of valuefuncmat.f90 = Z'2AE914E37010']
[Allocated item 8 (size 27409608) at line 154 of valuefuncmat.f90 = Z'2AE91685B010']
[Deallocated item 8 (size 27409608, at Z'2AE91685B010') at line 166 of valuefuncmat.f90]
[Deallocated item 4 (size 14808, at Z'2AE913143070') at line 88 of valuefuncmat.f90]
[Deallocated item 5 (size 27409608, at Z'2AE913413010') at line 88 of valuefuncmat.f90]
[Deallocated item 7 (size 27409608, at Z'2AE914E37010') at line 88 of valuefuncmat.f90]
[Allocation (size 281732479017624) at line 170 of valuefuncmat.f90 failed]
Runtime Error: valuefuncmat.f90, line 170: Cannot allocate array temporary - out of memory
Program terminated by fatal error
[Deallocated item 2 (size 65537, at Z'2AE913123030')]
[Deallocated item 3 (size 65537, at Z'2AE913133050')]
[Deallocated item 1 (size 65537, at Z'2AE913113010')]
Abort (core dumped)
Let me highlight part of that memory-trace output:
[Allocation (size 281732479017624) at line 170 of valuefuncmat.f90 failed]
As roygvib noted in their comment, this appears to be the issue that you need to address.

Related

How do I solve this error "An argument of 'series float' type was used but a 'input float' is expected" in Pine Script Version 5

I'm writing a Pine Script Indicator and I'm getting 4 errors and one warning after compiling:
Cannot call 'hline' with argument 'price'='upperBound'. An argument of 'series float' type was used but a 'input float' is expected
Cannot call 'hline' with argument 'price'='lowerBound'. An argument of 'series float' type was used but a 'input float' is expected
Cannot call 'fill' with argument 'hline1'='upperBound'. An argument of 'series float' type was used but a 'hline' is expected
Cannot call 'fill' with argument 'hline2'='lowerBound'. An argument of 'series float' type was used but a 'hline' is expected
(1) warning: The transp argument is deprecated. We recommend using color.new() or color.rgb() functions to specify the transparency of the plots instead. Additionally, note that transp has no effect in plots where the color is calculated at runtime
This is my Pine Script Code:
'''
//#version=5
// Define the number of bars to be analyzed for finding clusters
clusterLength = input(title="Cluster Length", defval=100)
// Define the number of standard deviations from the mean to determine the cluster
stdDev = input(title="Number of Standard Deviations", defval=2.0)
// Calculate the mean and standard deviation for the defined number of bars
mean = ta.sma(close, clusterLength)
stddev = ta.stdev(close, clusterLength)
// Plot the upper and lower bounds of the clusters as horizontal lines
upperBound = mean + stddev * stdDev
lowerBound = mean - stddev * stdDev
hline(upperBound, color=color.red, linewidth=2, title="Upper Bound")
hline(lowerBound, color=color.blue, linewidth=2, title="Lower Bound")
// Fill the area between the bounds to visually represent the cluster
fill(upperBound, lowerBound, color=color.gray, transp=70)
'''
I would appreciate if you provide a solution.
Thanks in advance
You cannot use dynamic values in hline().
You can try using plot() or line instead.
And you should be calling the fill() function with plots or hlines. upperBound and lowerBound are just variables.
See the signature below:
fill(hline1, hline2, color, title, editable, fillgaps, display) → void
fill(plot1, plot2, color, title, editable, show_last, fillgaps, display) → void

Numpy's hstack troubles with Numba

I am having trouble compiling a simple function in no-Python mode with Numba:
#njit
def fun(x,y):
points = np.hstack((x,y))
return points
a = 5
b = 2
res = fun(a,b)
While this very simple script works without the #njit decorator, if run with it throws the error:
TypingError: Failed in nopython mode pipeline (step: nopython frontend)
No implementation of function Function(<function hstack at 0x7f491475fe50>) found for signature:
>>> hstack(UniTuple(int64 x 2))
There are 4 candidate implementations:
- Of which 4 did not match due to:
Overload in function '_OverloadWrapper._build.<locals>.ol_generated': File: numba/core/overload_glue.py: Line 129.
With argument(s): '(UniTuple(int64 x 2))':
Rejected as the implementation raised a specific error:
TypeError: np.hstack(): expecting a non-empty tuple of arrays, got UniTuple(int64 x 2)
raised from /usr/local/lib/python3.8/dist-packages/numba/core/typing/npydecl.py:748
During: resolving callee type: Function(<function hstack at 0x7f491475fe50>)
During: typing of call at <ipython-input-41-7a0a3bcd4b1a> (28)
File "<ipython-input-41-7a0a3bcd4b1a>", line 28:
def fun(x, y):
points = np.hstack((x, y))
^
If I try to stack one scalar and one array (which it might be the case in the original function from which this problem arised), the behavior doesn't change:
b = np.ones(3)
res = fun(a,b)
TypingError: Failed in nopython mode pipeline (step: nopython frontend)
No implementation of function Function(<function hstack at 0x7f491475fe50>) found for signature:
>>> hstack(Tuple(int64, array(float64, 1d, C)))
There are 4 candidate implementations:
- Of which 4 did not match due to:
Overload in function '_OverloadWrapper._build.<locals>.ol_generated': File: numba/core/overload_glue.py: Line 129.
With argument(s): '(Tuple(int64, array(float64, 1d, C)))':
Rejected as the implementation raised a specific error:
TypeError: np.hstack(): expecting a non-empty tuple of arrays, got Tuple(int64, array(float64, 1d, C))
raised from /usr/local/lib/python3.8/dist-packages/numba/core/typing/npydecl.py:748
During: resolving callee type: Function(<function hstack at 0x7f491475fe50>)
During: typing of call at <ipython-input-42-39bffd13df71> (28)
File "<ipython-input-42-39bffd13df71>", line 28:
def fun(x, y):
points = np.hstack((x, y))
This is very puzzling to me. I am using Numba 0.56.4—which should be the last stable release.
A very similar behavior happens with np.concatenate, too.
Any suggestion would much appreciated.
Thank you!

How to subset a 1-d array using a boolean 1-d array in numba decorated function?

I gotta say, numba seems to be usable only in extremely simplistic use cases carefully designed to be presented in talks
I can run the following code just fine:
def rt(hi):
for i in hi:
hi_ = i == hi
t = hi[hi_]
return None
rt(np.array(['a','b','c','d'],dtype='U'))
But, when i decorate the above code with njit:
#njit
def rt(hi):
for i in hi:
hi_ = i == hi
t = hi[hi_]
return None
rt(np.array(['a','b','c','d'],dtype='U'))
I get the following error:
---------------------------------------------------------------------------
TypingError Traceback (most recent call last)
<ipython-input-34-eadef1d0ecee> in <module>
5 t = hi[hi_]
6 return None
----> 7 rt(np.array(['a','b','c','d'],dtype='U'))
~/miniconda/envs/IndusInd_credit_cards_collections_scorecard_/lib/python3.8/site-packages/numba/core/dispatcher.py in _compile_for_args(self, *args, **kws)
418 e.patch_message(msg)
419
--> 420 error_rewrite(e, 'typing')
421 except errors.UnsupportedError as e:
422 # Something unsupported is present in the user code, add help info
~/miniconda/envs/IndusInd_credit_cards_collections_scorecard_/lib/python3.8/site-packages/numba/core/dispatcher.py in error_rewrite(e, issue_type)
359 raise e
360 else:
--> 361 raise e.with_traceback(None)
362
363 argtypes = []
TypingError: Failed in nopython mode pipeline (step: nopython frontend)
No implementation of function Function(<built-in function getitem>) found for signature:
>>> getitem(array([unichr x 1], 1d, C), Literal[bool](False))
There are 22 candidate implementations:
- Of which 20 did not match due to:
Overload of function 'getitem': File: <numerous>: Line N/A.
With argument(s): '(array([unichr x 1], 1d, C), bool)':
No match.
- Of which 1 did not match due to:
Overload in function 'GetItemBuffer.generic': File: numba/core/typing/arraydecl.py: Line 162.
With argument(s): '(array([unichr x 1], 1d, C), bool)':
Rejected as the implementation raised a specific error:
TypeError: unsupported array index type bool in [bool]
raised from /home/sarthak/miniconda/envs/IndusInd_credit_cards_collections_scorecard_/lib/python3.8/site-packages/numba/core/typing/arraydecl.py:68
- Of which 1 did not match due to:
Overload in function 'GetItemBuffer.generic': File: numba/core/typing/arraydecl.py: Line 162.
With argument(s): '(array([unichr x 1], 1d, C), Literal[bool](False))':
Rejected as the implementation raised a specific error:
TypeError: unsupported array index type Literal[bool](False) in [Literal[bool](False)]
raised from /home/sarthak/miniconda/envs/IndusInd_credit_cards_collections_scorecard_/lib/python3.8/site-packages/numba/core/typing/arraydecl.py:68
During: typing of intrinsic-call at <ipython-input-34-eadef1d0ecee> (5)
File "<ipython-input-34-eadef1d0ecee>", line 5:
def rt(hi):
<source elided>
hi_ = i == hi
t = hi[hi_]
^
How to subset a 1-d array using a boolean 1-d array in numba decorated function?

Numba jit unknown error during python function

I made this function, but numba always give me error. Both chr_pos and pos are 1D arrays. What can be the problem?
#nb.njit
def create_needed_pos(chr_pos, pos):
needed_pos=[]
needed_pos=np.array(needed_pos,dtype=np.float64)
for i in range(len(chr_pos)):
for k in range(len(pos)):
if chr_pos[i] == pos[k]:
if i==1 and k==1:
needed_pos=pos[k]
else:
a=pos[k]
needed_pos=np.append(needed_pos,[a])
return needed_pos
needed_pos=create_needed_pos(chr_pos, pos)
The errors:
warnings.warn(errors.NumbaDeprecationWarning(msg,
<input>:1: NumbaWarning:
Compilation is falling back to object mode WITHOUT looplifting enabled because Function "create_needed_pos" failed type inference due to: Cannot unify array(float64, 1d, C) and int32 for 'needed_pos.1', defined at <input> (5)
File "<input>", line 5:
<source missing, REPL/exec in use?>
During: typing of intrinsic-call at <input> (9)
File "<input>", line 9:
<source missing, REPL/exec in use?>
The message
Cannot unify array(float64, 1d, C) and int32 for 'needed_pos.1'
is telling you that you are trying to assign an integer variable to an array. That happens in this line:
needed_pos=pos[k]
You can do that in normal Python, but Numba requires static types. You must assign an array of floats to an array of floats. For example, replacing the line by
needed_pos = pos[k:k+1]
The same error message says you are trying to assign an int, and this indicates that pos receives an array of ints. You must pass an array of floats instead.
After those changes, Numba still complains here:
needed_pos = []
needed_pos = np.array(needed_pos, dtype=np.float64)
with the message
numba.core.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Cannot infer the type of variable 'needed_pos', have imprecise type: list(undefined)<iv=None>.
because it doesn't know the type of the elements that needed_pos will contain.
You can replace those two lines with one that creates an array of size zero with a known type:
needed_pos = np.array((0,), dtype=np.float64)
Now the program compiles and produces the same result with or without Numba.
But a problem remains. Numpy arrays work best when they have a fixed size. If you are continuously adding elements you'd better use lists (Numba lists in this case). This way for example:
#nb.njit
def create_needed_pos(chr_pos, pos):
needed_pos = nb.typed.List.empty_list(nb.float64)
for i in range(len(chr_pos)):
for k in range(len(pos)):
if chr_pos[i] == pos[k]:
if i == k == 1:
needed_pos = nb.typed.List([pos[k]])
else:
needed_pos.append(pos[k])
return needed_pos

Fortran: Gradient method for minimum of a 2D-function

I made this simple program to compute the minimum of a goal function using the gradient method. I test it for a simple 1D function (http://en.wikipedia.org/wiki/Gradient_descent) and it's work very well giving to me the exact position of the minimum.
I generalize it to a 2D function: x^4+2y^4 which as only one zero in (0,0) as follow:
real*8 function cubic(xvect_old,n)
real(8), dimension(n) :: xvect_old
cubic = 4.d0*(xvect_old(1)**3.d0)+8.d0*(xvect_old(2)**3.d0)
!cubic = 4.d0*(xvect_old(1)**3.d0)-9.d0*(xvect_old(1)**2.d0)
end function cubic
program findmin
implicit none
integer, parameter :: n=2
integer :: i,j,m
real(8) :: cubic
real(8), dimension(n) :: xvect,xvect_old
real(8) :: eps,max_prec
m=30
eps = 0.01d0 ! step size
xvect_old =0.d0
xvect(1) = 2.2d0 ! first guess
xvect(2) = 3.1d0
max_prec = 1e-16
do while ( abs(xvect(1) - xvect_old(1)) > max_prec .and. &
& abs(xvect(2) - xvect_old(2)) > max_prec)
xvect_old(1:2) = xvect(1:2)
xvect(1:2) = xvect_old(1:2) - eps*cubic(xvect_old,n)
end do
print*, "Local minimum occurs at : ", xvect(1:2)
end program findmin
But it give to me, also if I am very near to the correct position (let's say, thanking as first guess (1.2,1.1) ) some large non correct solutions:
(-0.5017 ; 0.3982)
Is the method implemented wrong or there is some lack in my understanding how accurate the method is? I know there are more advanced methods like genetic algorithm which are, maybe, faster but are they also easy to implement?
Thanks a lot.
cubic is supposed to return the gradient and thus must be a vector.
Try the following:
module functions
implicit none
contains
function cubic(x,n) result(g)
integer, intent(in) :: n
real*8, dimension(n), intent(in) :: x
real*8, dimension(n) :: g
g =(/ 4.d0*(x(1)**3.d0), 8.d0*(x(2)**3.d0) /)
end function cubic
end module
program SOGradient
use functions
implicit none
integer, parameter :: n=2
integer :: i,j,m
real(8), dimension(n) :: xvect,xvect_old
real(8) :: eps,max_prec
m=30
eps = 0.01d0 ! step size
xvect_old =(/ 0.d0, 0d0 /)
! first guess
xvect = (/ 2.2d0, 3.1d0 /)
max_prec = 1e-12
do while ( MAXVAL(ABS(xvect-xvect_old))>max_prec )
xvect_old = xvect
xvect = xvect_old - eps*cubic(xvect_old,n)
end do
print*, "Local minimum occurs at : ", xvect
end program SOGradient
Of course the closer you get to the minimum, the smaller the step so the convergence is really slow. I would suggest using a newton raphson type method to find where the gradient is zero.
So to find the minimum of f(x,y) find the gradient g(x,y)=[gx,gy]=[df/dx,df/dy] and the gradient of the gradient h(x,y) = [[ dgx/dx, dgx/dy],[dgy/dx, dgy/dy]]
Now you iterate with
[x,y] -> [x,y] - h(x,y)^(-1)*g(x,y)
In you case f(x,y) = x^4+2*y^2, g=[4*x^3, 8*y^3] and h=[[12*x^2,0],[0,24*y^2]]
[x,y] -> [x,y] - [x/3,y/3]
which obviously has a solution in (0,0), but converges there much faster.