Announcement

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

  • How to embed Quadrature() in optimize()

    Dear Statalist members,

    I'm using Stata 17 SE. I would like to know whether it is possible to embed Quadrature( ) in optimize(), and if yes, how to do so.

    As demonstrated in the toy examples below, I know how to use Quadrature( ) and optimize() separately, but when I tried to embed one into another, I got error message: "type mismatch: exp.exp: transmorphic found where struct expected".

    Here is how I use optimize(), and it works:
    Code:
    cap mata: mata drop S
    cap mata: mata drop Optfunc1()
    mata:
    void Optfunc1(todo, b, P, x, v, g, H)
    {
    v =( P -logistic(b *x) )^2
    }
    
    P =.3
    x = 1
    S =optimize_init()
    optimize_init_evaluator(S, &Optfunc1())
    optimize_init_which(S, "min")
    optimize_init_argument(S, 1, P)
    optimize_init_argument(S, 2, x)
    optimize_init_params(S, 0)
    b =optimize(S); b
    end
    
    Iteration 0:   f(p) =        .04  
    Iteration 1:   f(p) =  .00010051  
    Iteration 2:   f(p) =  6.024e-08  (not concave)
    Iteration 3:   f(p) =  4.736e-09  (not concave)
    Iteration 4:   f(p) =  3.710e-10  
      -.8473895862
    Here is how I use Quadrature(), and it works as well:
    Code:
    cap mata: mata drop Q
    cap mata: mata drop Intfunc1()
    mata:
    real scalar Intfunc1(real scalar x, real scalar b)
    {
    return( logistic(b *x) *x *normalden(x,-.5,1) )
    }
    
    b =-1.5
    Q =Quadrature()
    Q.setEvaluator(&Intfunc1())
    Q.setLimits((., .))
    Q.setArgument(1, b)
    px =Q.integrate(); px
    end
    
    -.5648941335
    However, I got error message when I tried something like this, where I attempted to execute Intfunc2() within Optfunc2():
    Code:
    cap mata: mata drop Q
    cap mata: mata drop Intfunc2()
    cap mata: mata drop S
    cap mata: mata drop Optfunc2()
    mata:
    real scalar Intfunc2(real scalar x, real scalar b)
    {
    return( logistic(b *x) *x *normalden(x,-.5,1) )
    }
    end
    
    mata:
    Px =.35
    Q  =Quadrature()
    Q.setEvaluator(&Intfunc2())
    Q.setLimits((., .))
    
    void Optfunc(todo, b, Px, Q, v, g, H)
    {
    Q.setArgument(1, b) //problem begins from this line
    px =Q.integrate()
    
    v =( Px -px )^2
    }
    
    S =optimize_init()
    optimize_init_evaluator(S, &Optfunc2())
    optimize_init_which(S, "min")
    optimize_init_argument(S, 1, Px)
    optimize_init_argument(S, 2, Q)
    optimize_init_params(S, 0)
    b =optimize(S); b
    end
    All examples above are for demonstration purposes only. I understand that there may be other ways to do these examples without using Quadrature() and optimize(). I hope that these toy examples are clear enough to convey my question. If anything is unclear, please let me know.

    Thank you very much for your help.

  • #2
    Originally posted by Chi-lin Tsai View Post
    I would like to know whether it is possible to embed Quadrature( ) in optimize(), and if yes, how to do so. . . . I know how to use Quadrature( ) and optimize() separately, but when I tried to embed one into another, I got error message: "type mismatch: exp.exp: transmorphic found where struct expected".
    Yeah, passing these built-in objects as a function's arguments and then trying to refer to them inside the function can be a little quirky.

    For these kinds of problem, I always resort to Mata's class programming in order to organize things . . . and you can pass an object of a user-defined class to an evaluator function and then reference it without Mata's balking.

    See the example code below for an intimation of how this approach can work in your case.
    Code:
    version 17
    
    clear *
    
    mata:
    mata set matastrict on
    
    real scalar function integrand(
            real scalar x,
            real scalar b)
        return( logistic(b * x) * x * normalden(x, -0.5, 1) )
    
    class Integration {
        private:
            class Quadrature scalar q
            void new()
        public:
            real scalar integral()
    }
    void function Integration::new() {
        q.setEvaluator(&integrand())
        q.setLimits( (., .) )
    }
    real scalar function Integration::integral(real scalar b) {
        q.setArgument(1, b)
        return(q.integrate())
    }
    
    void function façade(
            real scalar todo,
            real rowvector B,
            real scalar px,
            class Integration scalar w,
            real scalar v,
            real rowvector G,
            real matrix H) {
        pragma unused todo; pragma unused G; pragma unused H
    
        v = ( (px - w.integral(B[1]))^2 )
    }
    
    class Optimum {
        private:
            transmorphic scalar s
            void new()
        public:
            void find()
    }
    void function Optimum::new() {
    
        s = optimize_init()
        optimize_init_evaluator(s, &façade())
        optimize_init_which(s, "min")
        
        class Integration scalar w
        optimize_init_argument(s, 2, w)
        optimize_init_params(s, 0)
    }
    void function Optimum::find(real scalar px) {
    
        optimize_init_argument(s, 1, px)
    
        printf("%10.8g\n", optimize(s))
    }
    
    void function demo() {
    
        class Optimum scalar o
        o.find(0.35)
    }
    
    demo()
    
    end
    
    exit
    (Mata's class programming is a little verbose and for that reason it might seem a bit daunting at first.)

    Unfortunately, you must pass a standalone function as the evaluator function for optimize() and Quadrature(), and moptimize() for that matter. See here and here, for example. And so, you're stuck with standalone functions for the evaluators.

    I haven't done so above in order to more closely conform to your code's approach, but in my work I relegate these standalone functions to wrapper-only service where inside them I call a method on the passed object for actual function evaluation..

    Comment

    Working...
    X