Announcement

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

  • optimize double-sum function

    Dear Statalisters,

    For a dataset sorted on variable x, I wish to maximize the following function with respect to alpha. Here is the Latex equivalent:

    \sum_i \sum_j [ \arctan(s_i / alpha) - \arctan(s_j / alpha) ]^2

    where s_i = (\Delta y_i / \Delta x_i) and s_j = (\Delta y_j / \Delta x_j). The \Delta operator indicates first differences and s_i, s_j are consecutive slopes. Note how the optimization problem involves a double-summation operator over i=1,2,...,n and j=1,2,...,n-1, hence the need to create n*(n-1) pairs of s_i and s_j.

    As an example, consider the sunspot dataset. Sort by x and calculate the first differences:

    use http://www.stata-press.com/data/r14/sunspot.dta
    rename spot y
    rename time x
    sort x
    generate dy = y[_n]- y[_n-1]
    generate dx = x[_n]- x[_n-1]
    keep if dy<.

    In Part 1 of the Mata code below, I take a view of dy and dx, and calculate all slopes dy/dx for every possible i,j pair where i!=j. I believe that this part works as expected.

    In Part 2 of the Mata code, I decide to deal with double-summation by treating the i_th slopes as `panels' and the j_th slopes as `within panel' observations. I also reformulated the problem as Manhattan distances in a matrix form which should give the same result but it involves more complex code. To me, the `panel' approach seems to somewhat reduce the complexity of the problem, but please share your thoughts too.

    My main concern is with the loop within the &eval function that is being optimized. I suspect that my literal translation of the optimization problem is inconsistent with Mata's optimize() engine. That is, for every i_th panel I calculate the colsum() of each panelsubmatrix() (i.e. the inner summation operator) and the loop accumulates for every i_th panel (i.e. the outer summation operator). Then, it is outside the loop that I specify that v should be optimized for the double-sum that is now reduced to just a scalar. This approach does not feel right to me, and also the end result is entirely unreasonable, but I am unable to see an alternative formulation.

    Please share your wisdom. As this is part of a paper, all useful responses will be acknowledged accordingly.
    many thanks, Demetris

    mata:
    mata clear
    stata("sort " + "x")
    st_view(dy=., ., "dy")
    st_view(dx=., ., "dx")

    // Part 1: get n*(n-1) pairs of slopes
    id = J(rows(dy)*(rows(dy)-1),1,0)
    si = J(rows(dy)*(rows(dy)-1),1,0)
    sj = J(rows(dy)*(rows(dy)-1),1,0)

    k = 0
    for(i=1; i<=rows(dy); i++) {
    for(j=1; j<=rows(dy); j++) {
    if (i!=j) {
    k=k+1
    id[k] = i
    si[k] = dy[i] / dx[i]
    sj[k] = dy[j] / dx[j] ;
    }
    }
    }

    // Part 2: optimize
    info = panelsetup(id, 1)

    void eval(todo, a, info, si, sj, v, g, H)
    {
    sum_ij = 0
    for (i=1; i<=rows(info); i++) {
    sum_ij = sum_ij ///
    + colsum( panelsubmatrix( ( atan(si:/a) :- atan(sj:/a) ):^2, i, info ) )
    }
    v = sum_ij
    }
    S = optimize_init()
    optimize_init_evaluator(S, &eval())
    optimize_init_evaluatortype(S, "gf0")
    optimize_init_which(S,"max")
    optimize_init_params(S, 1)
    optimize_init_argument(S, 1, info)
    optimize_init_argument(S, 2, si)
    optimize_init_argument(S, 3, sj)

    a = optimize(S)
    end
Working...
X