program define flexconstraints, rclass
*!	program flexconstraints		version 1.6		24Nov2017

*	Program to construct the constraints to be applied to
*	a flexible cost function when it is estimated jointly with the
*	auxiliary factor demand equations.

*	Implemented first for the translog

*	Assume that -flexmake- has just been executed.  Start by incorporating all
*	of its returned macros.

	version 11.1

	syntax , [INNames(string) verbose depvar(string) inputs(string) shares(string) prices(string)  ///
			ownprices(string) ownprices2(string) crossprices(string) GLobals  ///
			ownoutputs(string) ownoutputs2(string) crossoutputs(string) outputsxprices(string) ///
			costalone debug]

	if "`verbose'"=="" {
		local shhh quietly
	}

	local innamestxt "Names of input variables from -innames- are: " as res "`innames'"
	local depvartxt "Dependent variable is: " as res "`depvar'"
	local inputstxt "Inputs are: " as res "`inputs'"
	local sharestxt "Shares are: " as res "`shares'"
	local pricestxt "Input prices are: " as res "`prices'"
	local ownpricestxt      "Transformed input price variables are: " as res "`ownprices'"
	local ownprices2txt     "Squared transformed input price variables are: " as res "`ownprices2'"
	local crosspricestxt    "Crossproducts of transformed input price variables are: " as res "`crossprices'"
	local ownoutputstxt     "Transformed output variables are: " as res "`ownoutputs'"
	local ownoutputs2txt    "Squared transformed output variables are: "  as res "`ownoutputs2'"
	local crossoutputstxt   "Crossproducts of transformed output variables are: "  as res "`crossoutputs'"
	local outputsxpricestxt "Crossproducts of outputs and prices are: " as res "`outputsxprices'"

	foreach opt in innames depvar inputs shares prices ownprices ownprices2 crossprices  ///
		ownoutputs ownoutputs2 crossoutputs outputsxprices {
		if "``opt''"=="" {
			if `"`r(`opt')'"'=="" {
				di as err "The option -`opt'- must be provided as either " `"-r(\`opt')-"' ///
					_n "(e.g. from a preceding execution of flexmake)"  ///
					_n "or as an option on the flexconstraints command line."
				exit 198
			}
			else {
				local `opt' `r(`opt')'
			}
		}
		else {
			local `opt' ``opt''
		}
		if "`debug'"~=""  {    /* DEBUG */
		  `shhh' di as txt `"``opt'txt'"'
		}
		else {
			  `shhh' di as txt "The option `opt' is: " as res `"``opt''"'
		}
	}

*	Factor demand equations differ between translog and generalized Leontief cost functions
*		For the translog, the demand equations have factor shares as dependent variables.
*		For the Generalized Leontief, factor quantities are the dependent variables.

*	Confirm that input quantity, share and price variables have same input names in the same order
	local i = 1
	foreach n of local innames {
		local nlngth = length("`n'")
		foreach vartype in inputs prices shares {
			if "`debug'"~=""  di substr(word("``vartype''",`i'),-`nlngth',.)    /* DEBUG */
			local sfx = substr(word("``vartype''",`i'),-`nlngth',.)
			assert "`sfx'"== "`n'"
		}
		local i = `i' + 1
	}

* Initialize
	local c = 1    //  Index the constructed constraints
	local K=wordcount("`innames'")  // Number of factor prices
	local M=wordcount("`ownoutputs'")  // Number of outputs

*	Symmetry conditions on share equations
	di as txt _n "Factor demand equation constraints:"  ///
			  _n "-----------------------------------"
	di as txt _n(2) "    Constraints imposing symmetry on the factor demand equations"
	local i = 1
	while `i' <= `K'-2 {
		local sh1=word("`shares'",`i')
    if "`debug'"~=""  di _n as txt "For the share equation: " as res "`sh1'"    /* DEBUG */
		local j = `i' + 1
		while `j' < `K'  {
			local sh2=word("`shares'",`j')
      if "`debug'"~=""  di _n as txt "With the share equation: " as res "`sh2'" /* DEBUG */
			local p1 = word("`ownprices'",`i')
			local p2 = word("`ownprices'",`j')

			di as res `"constraint `c' _b[`sh1':`p2']  =  _b[`sh2':`p1']  "'
			constraint `c' _b[`sh1':`p2']  =  _b[`sh2':`p1']
			local test`c' _b[`sh1':`p2']  =  _b[`sh2':`p1']

			local c = `c' + 1
			local j = `j' + 1
		}
		local i = `i' + 1
	}

*	Constraints that impose homogeneity of degree zero in prices on the share equations
	di as txt _n "    Constraints imposing homogeneity of degree zero in prices on the factor demand equations"
	local i = 1
	while `i' <= `K'-1 {
		local constraint
		local plus
		local sh1=word("`shares'",`i')
		if "`debug'"~=""  di _n as txt "For the share equation: " as res "`sh1'"    /* DEBUG */
		local j = 1
		while `j' <= `K'  {
			local p2 = word("`ownprices'",`j')

			local constraint `constraint' `plus' _b[`sh1':`p2']

			local plus +
			local j = `j' + 1
		}
		di as res `"constraint `c' `constraint' = 0"'
		constraint `c' `constraint' = 0
		local c = `c' + 1
		local i = `i' + 1
	}

*	Cost function constraints:
*		First-order price coefficients in cost function equal to constants in share equations
	di as txt _n "Cost function constraints:"  ///
			  _n "--------------------------"

	di as txt _n "    Constraints imposing Shephard's Lemma & homogeneity of degree one in prices on the cost function"
	di as txt _n "    *  Constraints between first-order price coefficients within the cost function"  ///
            _n "          and constant terms in the share equations (imposing Shephard's Lemma)"
	local plus
	local sumofconstants
	local sumof1storder
	local sumof1storderco  //  Cost only version
	local i = 1
	while `i' <= `K'-1 {

		local sh1=word("`shares'",`i')
		local p1 = word("`ownprices'",`i')

		di as res `"constraint `c' _b[`depvar':`p1']  =  _b[`sh1':_cons]"'
		constraint `c' _b[`depvar':`p1']  =  _b[`sh1':_cons]
		local test`c' _b[`depvar':`p1']  =  _b[`sh1':_cons]

		local sumofconstants `sumofconstants' `plus' _b[`sh1':_cons]
		local sumof1storder   `sumof1storder'   `plus' _b[`depvar':`p1']
		local sumof1storderco `sumof1storderco' `plus' _b[`p1']

		local plus +

		local c = `c' + 1
		local i = `i' + 1
	}
	di as txt _n "    *  Constraint across first-order price coefficients within the cost function"  ///
            _n "          (imposing linear homogeneity of factor prices)"
	local p1 = word("`ownprices'",`K')
	di as res `"constraint `c' `sumof1storder' + _b[`depvar':`p1']  =  1.0 "'
	constraint `c' `sumof1storder' + _b[`depvar':`p1']  =  1.0
	local test`c' `sumof1storder' + _b[`depvar':`p1']  =  1.0

	//  Constraints when only the cost function is estimated e.g. by -cnsreg-
	if "`costalone'"=="costalone" {
		local thouplusc = `c' + 1000
		constraint `thouplusc' `sumof1storderco' + _b[`p1']  =  1.0
		local test`thouplusc' `sumof1storderco' + _b[`p1']  =  1.0
	}

	local c = `c' + 1

*	Cost function constraints:
*		Second-order price coefficients in cost function must sum to zero to assure linear homogeneity in prices
	di as txt _n "    *  Constraints across second-order price coefficients within the cost function"  ///
            _n "          (imposing linear homogeneity of factor prices)"
	local i = 1
	while `i' <= `K' {
		local plus
		local sumof2ndorder
		local sumof2ndorderco  // Cost only version
		local sh1=word("`shares'",`i')
		if "`debug'"~=""  if "`debug'"~=""  di _n as txt "For the share equation: " as res "`sh1'"  /* DEBUG */
		local j = 1
		while `j' <= `K' {
			local sh2=word("`shares'",`j')
			if "`debug'"~=""  di _n as txt "With the share equation: " as res "`sh2'" /* DEBUG */
			local p1 = word("`ownprices'",`i')
			local p2 = word("`ownprices'",`j')

			if "`p1'"=="`p2'" {
				local half  #c.__half
			}
			else {
				local half
			}

			local sumof2ndorder   `sumof2ndorder'   `plus' _b[`depvar':`p2'#`p1'`half']
			local sumof2ndorderco `sumof2ndorderco' `plus' _b[`p2'#`p1'`half']

			local plus +

			local j = `j' + 1
		}
		di as res `"constraint `c' `sumof2ndorder'  =  0"'
		constraint `c' `sumof2ndorder'  =  0
		local test`c' `sumof2ndorder'  =  0

		//  Constraints when only the cost function is estimated e.g. by -cnsreg-
		if "`costalone'"=="costalone" {
			local thouplusc = `c' + 1000
			constraint `thouplusc' `sumof2ndorderco'  =  0
			local test`thouplusc' `sumof2ndorderco'  =  0
		}

		local c = `c' + 1
		local i = `i' + 1
	}
	//  Constrain sum of the coefficients of the squared prices to equal 0
	local sumof2ndorder
	local sumof2ndorderco  // Cost only version
	local plus
	local i = 1
	while `i' <= `K' {
			local p1 = word("`ownprices'",`i')
			local p2 = word("`ownprices'",`i')
			local half  #c.__half
			local sumof2ndorder   `sumof2ndorder'   `plus' _b[`depvar':`p2'#`p1'`half']
			local sumof2ndorderco `sumof2ndorderco' `plus' _b[`p2'#`p1'`half']
			local plus +

		local i = `i' + 1
	}
	di as res `"constraint `c' `sumof2ndorder'  =  0"'
	constraint `c' `sumof2ndorder'  =  0
	local test`c' `sumof2ndorder'  =  0

	//  Constraints when only the cost function is estimated e.g. by -cnsreg-
	if "`costalone'"=="costalone" {
		local thouplusc = `c' + 1000
		constraint `thouplusc' `sumof2ndorderco'  =  0
		local test`thouplusc' `sumof2ndorderco'  =  0
	}

	local c = `c' + 1

*		Second-order price coefficients in cost function equal to first-order coefficients in share equations
	di as txt _n "    *  Constraints between each second-order price coefficient in the cost function"  ///
	          _n "       and the coefficient on the same price in the corresponding factor demand equation"  ///
	          _n "       (imposing Shephard's Lemma)."  ///
	          _n "       Some of these constraints are redundant.  Use the largest full-rank subset."

*     Compose the constraints on the ownprice^2 coefficients to incorporate the "__half" when required
	local i = 1
	while `i' <= `K'-1 {

		local sh1=word("`shares'",`i')
    if "`debug'"~=""  di _n as txt "For the share equation: " as res "`sh1'"    /* DEBUG */

		local cp1 = word("`ownprices2'",`i')
		local p1 = word("`ownprices'",`i')

		di as res `"constraint `c' _b[`depvar':`cp1']  =  _b[`sh1':`p1']"'

		constraint `c' _b[`depvar':`cp1']  =  _b[`sh1':`p1']
		local test`c' _b[`depvar':`cp1']  =  _b[`sh1':`p1']

		local c = `c' + 1
		local i = `i' + 1
	}

*     Then compose the constraints on the cross-price coefficients
	local i = 1
	while `i' <= `K'-1 {

		local sh1=word("`shares'",`i')
    if "`debug'"~=""  di _n as txt "For the share equation: " as res "`sh1'"    /* DEBUG */
		local j = `i' + 1
		while `j' <= `K' {
			local sh2=word("`shares'",`j')
      if "`debug'"~=""  di _n as txt "With the share equation: " as res "`sh2'" /* DEBUG */
			local p1 = word("`ownprices'",`i')
			local p2 = word("`ownprices'",`j')

			di as res `"constraint `c' _b[`depvar':`p1'#`p2']  =  _b[`sh1':`p2']"'

			constraint `c' _b[`depvar':`p1'#`p2']  =  _b[`sh1':`p2']
			local test`c' _b[`depvar':`p1'#`p2']  =  _b[`sh1':`p2']

			local c = `c' + 1
			local j = `j' + 1
		}

		local i = `i' + 1
	}

* Constraints on coefficients of interactions between outputs and prices
	di as txt _n "    *  Constraints on coefficients of interactions between output(s) and prices"  ///
	          _n "          within the cost function (imposing linear homogeneity w.r.t. prices)"
	local sumofyxp
	local sumofyxpco  //  Cost only version
	foreach m of numlist  1/`M' {  // For each of the M outputs
		local plus
 		local y=word("`ownoutputs'",`m')
		foreach i of numlist 1/`K' {  // For each of the K input prices
			local p = word("`ownprices'",`i')
			local sumofyxp   `sumofyxp'   `plus' _b[`depvar':`y'#`p']
			local sumofyxpco `sumofyxpco' `plus' _b[`y'#`p']
			local plus +
		}
		di as res `"constraint `c' `sumofyxp' =  0.0 "'
		constraint `c' `sumofyxp' =  0.0
		local test`c' `sumofyxp'  =  0.0

		//  Constraints when only the cost function is estimated e.g. by -cnsreg-
		if "`costalone'"=="costalone" {
			local thouplusc = `c' + 1000
			constraint `thouplusc' `sumofyxpco'  =  0
			local test`thouplusc' `sumofyxpco'  =  0
		}

		local c = `c' + 1
		local sumofyxp
		local sumofyxpco  //  Cost only version
	}

	di as txt _n "    *  Constraints on coefficients of interactions between output(s) and prices"  ///
	          _n "          between the cost function and the K-1 factor demand equations"  ///
	          _n "          (imposing Shephard's Lemma)."
	foreach m of numlist  1/`M' {  // For each of the M outputs
 		local y=word("`ownoutputs'",`m')
		local Km1 = `K' - 1
		foreach i of numlist 1/`Km1' {  // For each of the K input prices, except the last
			local p = word("`ownprices'",`i')
			local sh = word("`shares'",`i')
			di as res `"constraint `c' _b[`depvar':`y'#`p']  =  _b[`sh':`y']"'
			constraint `c' _b[`depvar':`y'#`p']  =  _b[`sh':`y']
			local test`c' _b[`depvar':`y'#`p']  =  _b[`sh':`y']
			local c = `c' + 1
		}
	}
	if "`costalone'"=="costalone" {
		di as txt _n "    *  When estimating the cost function with a single equation estimator"  ///
				  _n "          such as {help cnsreg}, the following constraints impose"  ///
				  _n "          linear homogeneity in prices."
		constraint list 1001/1999
	}

	local Nconstraints = `c' - 1
	foreach c of numlist `Nconstraints'/1 {
		return local test`c' `test`c''
		if "`globals'"~="" global test`c' `test`c''
		if "`costalone'"=="costalone" {
			local thouplusc = `c' + 1000
			return local test`thouplusc' `test`thouplusc''
			if "`globals'"~="" global test`thouplusc' `test`thouplusc''
		}
	}

	return local Nconstraints `c'

	return add

end
*	Version 1.0 15Jul2012 Developed to replicate Christensen & Greene (1976)
*	Version 1.1 4Jul2017  First working version requires the option -innames-
*	version 1.2 10Jul2017 Since new version of flexmake saves r(innames), make innames optional.
*	version 1.3 17Aug2017 Add constraint that all squared factor price terms sum to zero
*				 		  Add returning logical statements for hypothesis tests, with globals option
*	version 1.4 21Nov2017 To avoid suppression of part of error messages, only use -di as err-
*	version 1.5 24Nov2017 Constraints on coefficients of interactions between outputs and prices
*	version 1.6 27Nov2017 For the K'th input price, omit the constraints between the coefficients
*							of the interaction with each output in the cost function
*							and that output in the corresponding share equation.