Value Function - Scoping problem

Hi everyone. I am trying to create a simple Value Function Iteration routine for a basic econ. problem.
I’m facing the common problem of global and local variable definition, but I don’t know how to correct in this case. Below is a simple version of the problem I am trying to solve:

agrid = 10
zgrid = 3

Pz = [0.11 0.85 0.04; 0.07 0.87 0.06; 0.03 0.85 0.12]

a = zeros(agrid, 1)
V = zeros(agrid, zgrid)
V_new = zeros(agrid, zgrid)

u = zeros(agrid)
erro = 100

while erro > 0.1
    for ia = 1:agrid
        for iz = 1:zgrid

            for ja = 1:agrid
                c = 0.02*a[ia] + exp(z[iz]) - a[ja]
                EV = transpose(Pz[iz,:])*V[ja,:]
                u[ja] = -1/c + 0.95*EV

            end
            Vmax, imax = findmax(u)
            V_new[ia,iz] = Vmax

        end
    end
erro = maximum(abs.(V_new - V))
V = V_new
end

The message I get is ‘UndefVarError: V not defined’. In this case, I don’t know how I can use ‘global definition variable’ or the ‘let’ operator to fix my problem.

Thanks!

I get ERROR: UndefVarError: z not defined.
If I define a z, and use global V = V_new in the last line I don’t get any error.

1 Like

It is a well-known behaviour, just put the code inside a function (not change is required), and it should be working.

Outside functions, variables like V or z are global (for be defined out of any function or loop), so you need to put inside the loop the sentences like “global V” to use them.

Yup. Use a function or stay in jupyter. For now, better to never use loops at top level scripts.

1 Like

Sorry, we could define z as z = [-0.43 0 0.43], for instance. In this case, I do not get an error, but the code does not run.

    agrid = 10
    zgrid = 3

    Pz = [0.11 0.85 0.04; 0.07 0.87 0.06; 0.03 0.85 0.12]

    a = zeros(agrid, 1)
    # Your definition of z
    z = [-0.43 0 0.43]
    V = zeros(agrid, zgrid)
    V_new = zeros(agrid, zgrid)

    u = zeros(agrid)
    erro = 100

    while erro > 0.1
        for ia = 1:agrid
            for iz = 1:zgrid
                
                for ja = 1:agrid
                    c = 0.02*a[ia] + exp(z[iz]) - a[ja]
                    EV = transpose(Pz[iz,:])*V[ja,:]
                    u[ja] = -1/c + 0.95*EV
                end
                Vmax, imax = findmax(u)
                V_new[ia,iz] = Vmax
            end
        end
        erro = maximum(abs.(V_new - V))
        V = V_new
        println("Error is $erro\tV is $V")
    end # of loop

end # Of main

main()

Yes, because your code is not right, z was not defined anyway in your original code, and it was used in line 19. So, there is an error, and we cannot fix it, because it is not a problem with the language, it is a logic error. Using a function (or using Jupyter( avoid the problem to access variables.

I have update the code with the z values you say, and it is working (I cannot help you more because I have not idea what are you trying to calculate).

1 Like

I think that’s a bit extreme. If the purpose of this piece of code if to compute V, it can say

V = let
   # ...
   # original code here
   # ...
   V
end

without requiring global annotations.

1 Like

Perfect! Now, my second (and main) doubt is the following:
We begin with V = [0 0 0; ...] and V_new = [0 0 0; ...]

In the first while iteration we have V_new = [-1.53 -1.0 -0.65; ...]. Hence the error is 1.53 and V becomes [-1.53 -1.0 -0.65; ...].

Since 1.53 > 0.1 we go to the second while iteration but now with V = [-1.53 -1.0 -0.65; ...]

Hence, by the algorithm, we updated V_new = [-2.53 -1.96 -1.57; ...].
In this case, the error should be maximum(abs.(V_new - V)) = max(abs.([-2.53 -1.96 -1.57; ...]- [-1.53 -1.0 -0.65; ...])).

However, in the second while iteration, the algorithm is updating V before computing the error, making maximum(abs.(V_new - V)) = max(abs.([-2.53 -1.96 -1.57; ...]- [-2.53 -1.96 -1.57; ....])) = 0 > 0.1 and stoping the iteration.

Matlab doesnt have this ‘behavior’ and dont know how to handle it in Julia.

I dont know if it is clear.
Any way, you already contributed a lot. Thanks!

You’ve got a lot of code here, so it’s hard to be sure, but I would suspect that the problem is here:

V = V_new

in Matlab, this would copy V_new and create a new vector called V. Any future changes to V_new would not affect V. In Julia, however, this just makes V a label for the same vector as V_new, so any changes to V_new will be shared with V. This is actually how all assignment operations in Julia work: Julia doesn’t silently copy things when you assign them or when you pass them to functions (unlike Matlab).

If you do want a copy, you can simply do: V = copy(V_new).

Perhaps that will help you figure out what’s different in the results you’re seeing.

3 Likes

It is precisely this point. I was skipping this detail in Julia.
Thanks a lot.