program define mob

    /**************************************************************/
    /* computes the Prais mobility index from period 1 to 2 and an*/
    /* appropriate bootstrap confidence interval                  */
    /*                                                            */
    /* syntax: mob <w> <d11> <d12> ... <d1M> <d21> <d22> ... <d2M>*/
    /*                                                            */
    /*         where <w> is a (longitudinal) weight               */
    /*               <dtm> are state dummies indicating whether or*/
    /*                     not an individual is in state m = 1..M */
    /*                     in period t = 1,2                      */
    /*                                                            */
    /* if no weights are needed, generate a variable with all     */
    /* values set to 1 and use it as the weight variable          */
    /*                                                            */
    /* Note: the bootstrap is a random process and may lead to    */
    /* missing values when statistics are calculated from the re- */
    /* sample; this problem vanishes with increasing sample size  */
    /*                                                            */
    /* for details see Biewen (2002): Bootstrap inference for     */
    /* inequality, mobility and poverty measurement, Journal      */
    /* of Econometrics, Vol. 108, pp. 317 – 342                   */
    /*                                                            */
    /* copyright Martin Biewen 2001                               */
    /**************************************************************/

    version 6



    /* parse syntax */

    syntax varlist



    /* set number of bootstrap replications and confidence level */

    tempname reps conf nobs

    scalar `reps' = 100

    scalar `conf' = 0.95

    scalar `nobs' = _N


    /* count  number of states */

    tempname nosts

    local i = 1

    while "``i''" != "" {

        local i = `i' + 1

    }

    scalar `nosts' = (`i' - 1 - 1)/2

    if `nosts' != int(`nosts') {

        di in red "error: wrong number of variables"

        exit

        }


    /* check if data consistent */

    tempvar check

    quietly gen `check' = 0

    local i = 2

    while `i' <= 1 + `nosts' {

        quietly replace `check' = `check' + ``i''

        quietly sum ``i''

        if r(min)<0 | r(max)>1 {

            di in red "error: state dummies must be either 0 or 1"

            exit

            }

        local i = `i' + 1

        }

    quietly count  if `check' != 1

    if r(N) != 0 {

        di in red "error: state dummies don't sum up to 1"

        exit

        }


    quietly replace `check' = 0

    local i = 1 + `nosts' + 1

    while `i' <= 1 + 2 * `nosts' {

        quietly replace `check' = `check' + ``i''

        quietly sum ``i''

        if r(min)<0 | r(max)>1 {

            di in red "state dummies must be either 0 or 1"

            exit

            }

        local i = `i' + 1

        }

    quietly count  if `check' != 1

    if r(N) != 0 {

        di in red "error: state dummies don't sum up to 1"

        exit

        }


    /* compute mobility estimate */

    mob_ind `0'


    tempname m

    scalar `m' = r(m)


    /* preserve and initialize post */

    preserve

    tempname postnam

    tempfile boot

    quietly postfile `postnam' bm using `boot', replace


    /* bootstrap loop */

    local i = 1

    while `i' <= `reps' {

        restore, preserve

        bsample

        mob_ind `0'

        post `postnam' sqrt(`nobs') * (r(m) - `m')

        local i = `i' + 1

        }

    postclose `postnam'



    /* generate lower and upper confidence bounds */

    use `boot', clear


    sort bm

    tempname lm um

    scalar `lm' = `m' - bm[`reps' - int((-(`conf'/2) + 0.5) * `reps')] / sqrt(`nobs')

    scalar `um' = `m' - bm[int((-(`conf'/2) + 0.5) * `reps')] / sqrt(`nobs')


    /* print out results */

    di _newline "------------------------------------------------------------------"
    di          "Prais mobility index,   estimate and bootstrap confidence interval"
    di          "------------------------------------------------------------------"
    di          "Confidence level = " %3.2f `conf' ",              " %5.0f `reps' " bootstrap replications
    di          "------------------------------------------------------------------"
    di          "Prais index = " in green %7.6f `m' in yellow  ", confidence interval " in green "["  %7.6f `lm' " ; " %7.6f `um' "]"
    di          "------------------------------------------------------------------"


    restore

end



program define mob_ind, rclass


    /* returns r(m)    */

quietly {

    /* initialize index */

    tempname m

    scalar `m' = 0


    /* count number of states */

    tempname nosts

    local i = 1

    while "``i''" != "" {

        local i = `i' + 1

    }

    scalar `nosts' = (`i' - 1 - 1)/2



    /* calculate products */

    tempvar w

    quietly gen `w' = `1'



    local i = 1

    while `i' <= `nosts' {


        tempvar d1`i' d2`i' n`i' d`i'


        local j = `i' + 1

        quietly gen `d1`i'' = ``j''

        local j = `i' + `nosts' + 1

        quietly gen `d2`i'' = ``j''


        quietly gen `n`i'' = `w' * `d1`i'' * `d2`i''

        quietly gen `d`i'' = `w' * `d1`i''


        /* calculate moments */

        tempname n d

        quietly sum `n`i''

        scalar `n' = r(mean)

        quietly sum `d`i''

        scalar `d' = r(mean)


        /* contribution to mobility index */

        scalar `m' = `m' + `n'/`d'


        local i = `i' + 1

        }


    /* finish calculation of index */

    scalar `m' = (`nosts' - `m')/(`nosts' - 1)


    /* return result */

    return scalar m = `m'

    }

end