Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • using optimize_init with a stataloop like forvalues

    I am trying to use the mata optimize function to solve some non-linear equations.
    I would like to do this many times with different values for the parameters of the nonlinear equation.

    mata code that works and provides a solution for a single run of a simplified version of my problem is:

    mata:
    void myeval(todo, t, y, g, H)
    {
    y= -(2-t)^2
    }
    S = optimize_init()
    optimize_init_evaluator(S, &myeval())
    optimize_init_params(S, 0)
    x = optimize(S)
    x
    end

    I would like to run this multiple times using a forvalues (or other looping) statement such as

    forvalues i = 2(2)40 {
    .
    .
    .
    }

    I know from previous statalist posts (and from trying it) that I cannot simply embed the mata code in the forvalues loop.

    I would like advice on how to run the optimize command many times with different parameters for the non-linear equation. Also, I would (of course) like to recover the optimized value for t and `i'. where t. maximizes y= -(`i'-t)^2

    Thanks

  • #2
    Originally posted by David Merriman View Post
    I am trying to use the mata optimize function to solve some non-linear equations.
    I would like to do this many times with different values for the parameters of the nonlinear equation.

    I would like advice on how to run the optimize command many times with different parameters for the non-linear equation. Also, I would (of course) like to recover the optimized value for t and `i'. where t. maximizes y= -(`i'-t)^2
    Try something like the following for starters.
    Code:
    version 18.0
    
    mata:
    mata set matastrict on
    
    void function myeval(real scalar todo, real rowvector T, real scalar i,
        real scalar y, real rowvector G, real matrix H) y = -(i - T[1])^2
    
    void function evaluate(real scalar i) {
    
        transmorphic scalar s
        s = optimize_init()
        optimize_init_evaluator(s, &myeval())
        optimize_init_params(s, 0)
        optimize_init_argument(s, 1, i)
        optimize_init_tracelevel(s, "none")
    
        st_local("result", st_tempname())
        st_numscalar(st_local("result"), optimize(s))
    }
    
    end
    
    forvalues i = 1/2 {
    
        mata: evaluate(`i')
        display in smcl as text "i = " %1.0f `i', ///
            as result "result = " %1.0f `result'
    
    }
    
    exit
    You can also feed the parameter directly to the evaluator function from Stata via something like the following (although I don't recommend such a backdoor way of going about this in general).
    Code:
    void function myeval(real scalar todo, real rowvector T, real scalar y,
            real rowvector G, real matrix H) {
    
        y = -(strtoreal(st_local("i")) - T[1])^2
    }
    There are other variations on this general theme of moving arguments back and forth between Stata and Mata.
    Last edited by Joseph Coveney; 21 Aug 2024, 20:54.

    Comment


    • #3
      Thanks that code was a very great help
      I really appreciate it.

      Comment


      • #4
        Originally posted by David Merriman View Post
        Thanks that code was a very great help
        I really appreciate it.
        I recommend one change to what I posted there, and that is to move the generation of the temporary scalar
        Code:
        st_local("result", st_tempname())
        out of the loop so that it's executed only once.

        The way it's written there, it will generate a new temporary scalar each passage through the Stata loop. Something like the following approach avoids that. (Changes highlighted in red.)
        Code:
        version 18.0
        
        mata:
        mata set matastrict on
        
        void function myeval(real scalar todo, real rowvector T, real scalar i,
            real scalar y, real rowvector G, real matrix H) y = -(i - T[1])^2
        
        void function evaluate(real scalar i) {
        
            transmorphic scalar s
            s = optimize_init()
            optimize_init_evaluator(s, &myeval())
            optimize_init_params(s, 0)
            optimize_init_argument(s, 1, i)
            optimize_init_tracelevel(s, "none")
        
            /* st_local("result", st_tempname()) */
            st_numscalar(st_local("result"), optimize(s))
        }
        
        end
        
        mata: st_local("result", st_tempname())
        
        forvalues i = 1/2 {
        
            mata: evaluate(`i')
            display in smcl as text "i = " %1.0f `i', ///
                as result "result = " %1.0f `result'
        
        }
        
        exit

        Comment

        Working...
        X