*! mcmccqreg 1.0.0 30May2013
*! author Matthew J. Baker
program mcmccqreg
	version 11.2
	if replay() {
		if (`"`e(cmd)'"' != "mcmccqreg") error 301
		Replay `0'
	}
	else Estimate `0'
end

program Estimate, eclass
	syntax varlist [if] [in], 				///
			[DRAWs(int 1000)				///
			BURN(int 0)						///
			ARATE(real .234)                ///
			SAMPLER(string)					///
			DAMPPARM(real 1)				///
			FROM(string)					///
			FROMVariance(string)			///
			SAVING(string)					///
			REPLACE							///
			APPEND							///
			THIN(int 1)						///
			JUMBLE							///
			NOISY							///
			TAU(real .5)					///
			MEDIAN							///
			CENSORvar(varname)]

	marksample touse
	gettoken lhs rhs : varlist

	markout `touse' `lhs' `rhs'

/* Option checking for conformity, etc. */

	/* Burn-in less than draws */

	if (`burn'>=`draws') {
		di as error "Error: The # of burn in draws must be less than # draws"
		exit
	}

	if "`sampler'"!="mwg" {
		local sampler "global"
	}

	if ("`censorvar'"=="`'") {
		tempname censorvar
		gen double `censorvar'=0 if `touse'
	}

/* Another thing to check - whether or not there are "too many" */
/* zeros in the data */

	tempname tauTooLow
	tempvar censorCheck
	gen double `censorCheck' = `lhs' <= `censorvar'
	quietly sum `censorCheck'
	scalar `tauTooLow' = r(mean) > `tau'
	if (`tauTooLow') {
		disp as err "Caution!!! Observations censored at tau-th percentile!\n"
		disp as err "Interpret results with extreme caution..."
	}

	/* Read in the data */

	mata: noisy   =st_local("noisy")
	mata: sampler =st_local("sampler")
	mata: tau     =strtoreal(st_local("tau"))
	mata: arate   =strtoreal(st_local("arate"))
	mata: alginfo ="standalone",st_local("sampler")
	mata: draws   =strtoreal(st_local("draws"))
	mata: dampparm=strtoreal(st_local("dampparm"))
	mata: burn    =strtoreal(st_local("burn"))
	mata: thin    =strtoreal(st_local("thin"))
	mata: jumble  =st_local("jumble")

	/* If the earlier powell estimator actually described in Powell '84 is desired */
	/* Overwrite tau and multiply by two to get 1                                  */

	if "`median'"=="median" {
		mata: weight=2
		mata: tau = .5
	}
	else {
		mata: weight=1
	}

	/* Set starting values */

	if ("`from'"!="") {
		mata: from=st_matrix("`from'")
	}
	else {
        qui reg `lhs' `rhs' if `touse'
		mata: from=st_matrix("e(b)")
		tempname from
		mata: st_matrix("`from'",from)
	}

	if ("`fromvariance'"!="") {
		mata: W=st_matrix("`fromvariance'")
	}
	else {
		mata: W=I(cols(from))*cols(from)
		tempname fromvariance
		mata: st_matrix("`fromvariance'",W)
	}

	/* Begin estimation process */

	mata: M=moptimize_init()
	mata: moptimize_init_evaluator(M,&quan())
	mata: moptimize_init_touse(M,"`touse'")
	mata: moptimize_init_evaluatortype(M,"gf0")
	mata: moptimize_init_depvar(M,1,"`lhs'")
	mata: moptimize_init_eq_indepvars(M,1,"`rhs'")

	mata: st_view(C=.,.,"`censorvar'","`touse'")
	mata: moptimize_init_userinfo(M,1,tau)
	mata: moptimize_init_userinfo(M,2,C)
	mata: moptimize_init_userinfo(M,3,weight)

	mata: moptimize_init_eq_coefs(M,1,from)	// Not necessary, but...
	mata: junk=moptimize_evaluate(M)

	/* set up and execute the amcmc run */

	mata: alginfo=sampler,"gf0","moptimize"
	mata: Draws = amcmc(alginfo,&quan(),from,W,draws,burn,dampparm,arate,ar=.,vals=.,lam=.,.,M,noisy)

	/* process all of the information that does not need further */
	/* manipulation */

	tempname arates arates_mean arates_min arates_max
	mata: st_matrix("`arates'",ar)
	mata: st_numscalar("`arates_mean'",mean(ar'))
	mata: st_numscalar("`arates_min'",min(ar))
	mata: st_numscalar("`arates_max'",max(ar))

	/* A function to process draws after they are done */

	tempname dof
	mata: mcmccqreg_process_draws(Draws,vals,jumble,thin,0,betaf=.,valsf=.)
	mata: st_numscalar("`dof'",rows(betaf))

	local dof=`dof'

	tempname b V valMean valMax valMin drawsKept
	mata: st_matrix("`b'",mean(betaf))
	mata: st_matrix("`V'",variance(betaf))

	mata: st_numscalar("`valMean'",mean(valsf))
	mata: st_numscalar("`valMax'",max(valsf))
	mata: st_numscalar("`valMin'",min(valsf))
	mata: st_numscalar("`drawsKept'",rows(valsf))

	mat colnames `b' = `rhs' _cons
	mat colnames `V' = `rhs' _cons
	mat rownames `V' = `rhs' _cons

	tempname nobs
	quietly tab `touse' if `touse'
	local nobs=`r(N)'

	ereturn clear
	ereturn post `b' `V', esample(`touse') obs(`nobs') dof(`dof')

	ereturn local title "Powell's mcmc-estimated censored quantile regression"
	ereturn local cmd "mcmccqreg"
	ereturn local indepvars `rhs'
	ereturn local depvar `lhs'
	ereturn local sampler `sampler'
	ereturn local saving `saving'
	ereturn local jumble `jumble'

	ereturn scalar draws=`draws'
	ereturn scalar burn=`burn'
	ereturn scalar thin=`thin'
	ereturn scalar damper=`dampparm'
	ereturn scalar opt_arate=`arate'
	ereturn scalar arates_mean=`arates_mean'
	ereturn scalar f_mean=`valMean'
	ereturn scalar f_max =`valMax'
	ereturn scalar f_min =`valMin'
	ereturn scalar draws_retained = `drawsKept'
	ereturn matrix arates=`arates'
	ereturn matrix b_init=`from'
	ereturn matrix V_init=`fromvariance'

		if "`saving'"!="" {
		preserve
		clear

		local exnames "`rhs' cons"
		getmata (`exnames')=betaf
		getmata (fun_val)=valsf

		gen t=_n
		if "`append'"=="append" {
			append using "`saving'"

		}
		else {
			qui save "`saving'", `replace'
		}
		restore
	}

	di _newline
	di as txt "`e(title)'"
	di as txt "     Observations:         " as res %10.0f `e(N)'
	di as txt "     Mean acceptance rate: " as res %10.3f `e(arates_mean)'
	di as txt "     Total draws:          " as res %10.0f `e(draws)'
	di as txt "     Burn-in draws:        " as res %10.0f `e(burn)'
	di as txt "     Draws retained:       " as res %10.0f `e(draws_retained)'
	if `e(thin)'!=1		{
	di as txt	_col(10) "*One of every " %1.0f `e(thin)' " draws kept"
				}
	if "`e(jumble)'"=="jumble" {
	di as txt			   _col(10) "*Draws Jumbled"
				}

	ereturn display
	di as txt " Value of objective function:   "
	di as txt "             Mean:         " as res %12.2f `e(f_mean)'
	di as txt "             Min:          " as res %12.2f `e(f_max)'
	di as txt "             Max:          " as res %12.2f `e(f_min)'
	if "`e(saving)'"!="" {
	di as txt "   Draws saved in: " "`e(saving)'"
						}
	di _newline
	di as txt "    *Results are presented to conform with Stata covention, but "
	di as txt "     are summary statistics of draws, not coefficient estimates. "
end

program Replay
	syntax
	ereturn display
end

mata:
void quan(M,todo,b,crit,g,H) {
	real colvector u,Xb,y,C
	real scalar tau

	Xb    =moptimize_util_xb(M,b,1)		 /* Xb linear combinations */
	y     =moptimize_util_depvar(M,1)	 /* dependent variable     */
	tau   =moptimize_util_userinfo(M,1) /* value for tau          */
	C     =moptimize_util_userinfo(M,2)	 /* Censoring points       */
	weight=moptimize_util_userinfo(M,3)
	u     =weight:*(y:-rowmax((C,Xb)))
	crit  =-(u:*(tau:-(u:<0))) /* Use neg. to get minimum */
}
void mcmccqreg_process_draws(real matrix Draws,
							 real matrix vals,
							 string scalar jumble,
							 real scalar thin,
							 real scalar burn,
							 transmorphic betaf,
							 transmorphic valsf)
{
	real scalar i
	real matrix ordVec

	Draws = Draws[burn+1::rows(Draws),]

	if (thin!=1) {
		keep=J(0,1,.)
		for (i=thin;i<=rows(Draws);i=i+thin) keep=keep \ i
	}
	else keep=(1::rows(Draws))

	if (jumble=="jumble") _jumble(keep)
	betaf=Draws[keep,]
	valsf=vals[keep,]
}
end