**REDUCE**
capture program drop reduce
program define reduce, rclass
version 9.0
syntax [namelist (min=2)] [if] [, ORIG(varlist) LABel(namelist) DNCare(namelist)]
local s `namelist'
capture unab s: `namelist'
marksample touse
local y: word 1 of `s'
local soluts: list s - y
	if "`dncare'"~="" {
		local soluts: list soluts | dncare
		}
unab vlist : _all

if "`namelist'" == "" {
	local start = r(start)
	local soluts "`r(sets)'"
	local y = r(y)
	local lastset `r(colsig)'
		if "`r(comm)'" ~= "" {
		 local lastset `r(comm)'
		}
	capture myboolean `start'
		mark nomis
		capture markout nomis `start'
	local soluts `lastset'
   if "`soluts'" == "" {
	di
		di as err "Error: Can Not Reduce - No Sets Identified as True"
		capture keep `vlist'
		exit
    }
}

unab nwvlist: _all
local nonvar: list soluts - nwvlist
foreach con of local nonvar {
	cnfgen `con'
	}

unab sets: `soluts'
	qui foreach var of local sets {
		capture replace `var'=. if nomis==0
		}
local size: word count `soluts'
local lengthy: word 1 of `soluts'
local num: length local lengthy

if `size' > 1 {
foreach var of local sets {
	local z=1
		forvalues j = 1/`num' {
			local `var'prt= substr("`var'", `j', 1)
			local configz`z' = "``var'prt'"
			local upper`var' = upper("`configz`z''")
			local letters "`letters' `upper`var''"
		    if "`configz`z''" == "`upper`var''" {
			local `var'bin 1
		    }
		    if "`configz`z''" ~= "`upper`var''" {
			local `var'bin 0
		    }
		local z = `z' +1
		local bin`var' "`bin`var''``var'bin'"
		}
	local finsets "`finsets' `bin`var''"
	}

local numsoluts: word count `finsets'
tokenize `finsets'
forvalues p = 1/`numsoluts' {
	local config`p' "``p''"
	}

local z 1
while `numsoluts'>1 {
local twodif "- -"
forvalues i = 1/`numsoluts' {
		local configcom`i'
	forvalues j = 2/`numsoluts' {
		if `i' < `j'{
		reduccomp `config`i'' `config`j''
		local redcon`z' `r(redcon)'
		local test: list redcon`z' & twodif
		local test: word count `test'
		 if `test' == 1 {
			local redcon`z' "`redcon`z''"
			local redcon`z': subinstr local redcon`z' " " "" , all
			local reduced "`reduced' `redcon`z''"
			local used "`used' `config`i'' `config`j''"
			 }
		 else {
			local redcon`z' "`redcon`z''"
			local redcon`z': subinstr local redcon`z' " " "" , all
			local configcom`i' "`configcom`i'' `redcon`z''"
				local nogood`i': word count `configcom`i''
					if `nogood`i'' == `numsoluts' - `i' {
						if `numsoluts' == 2 {
							local finred "`finred' `config1' `config2'"
							}
						else {
			  				local finred "`finred' `config`i''"
						}
		  }
		 }
		}
	local z = `z' + 1
	}
}
local numused: word count `used'
local lastone: list used - config`numsoluts'
local lastused: word count `lastone'
if `numused' == `lastused'{
	local finred "`finred' `config`numsoluts''"
	}
local reduced: list uniq reduced
local numsoluts: word count `reduced'
	if `numsoluts' == 1{
		local finred "`finred' `reduced'"
	}
tokenize `reduced'
local newdash 2
forvalues k=1/`numsoluts' {
	local config`k' ``k''
	local config`k': subinstr local config`k' "-" "`newdash'" , all
	}
local reduced
}
local finred: list uniq finred
local finred: list finred - used

*Moving Back to Letters
local letters: list uniq letters
tokenize `letters'
foreach c of local finred {
  forvalues j = 1/`num' {
	local `j'part = substr("`c'", `j', 1)
		if "``j'part'" == "1" {
			local `j'part = "``j''"
			local finsol "`finsol' ``j'part'"
			}
	local `j'part = substr("`c'", `j', 1)
		if "``j'part'" == "0" {
			local `j'part = lower("``j''")
			local finsol "`finsol' ``j'part'"
			}
	local `j'part = substr("`c'", `j', 1)
		if "``j'part'" > "1" {
			local `j'part
			local finsol "`finsol' ``j'part'"
			}
      }
 capture local `finsol' "`finsol'"
 capture local finsol: subinstr local finsol " " "", all
 capture local finsols "`finsols' `finsol'"
 capture local finsol
}
local finsols: list uniq finsols
local nsols: word count `finsols'
	if `nsols' == 0 {
		di as err "Error: All Possible Sets Entered as True - Reduces to Nothing"
		}
	else{
		di
		if "`dncare'" == "" {
			di in yell "`size'" in green " Solutions Entered as True"
		}
		if "`dncare'" ~= "" {
			local sets: list sets - dncare
			local numtrue: word count `sets'
			local numdnc: word count `dncare'
			di in yell "`numtrue'" in green " Solutions Entered as True"
			di in yell "`numdnc'" in green " Solutions Treated as Do Not Cares"
		}
		di
		di in green "{ul:Minimum Configuration Reduction Set}"
		di in yell "`finsols'"
		local onefin: word count `finsols'
		if `onefin'>1 {
		truthtab `y' `sets', fromreduce(`finsols') indvars(`letters')
		local finsols `r(finsols)'
		}
		di
		di
		di in green "{ul:Final Reduction Set}"
		coverage `y' `finsols' if `touse', orig(`orig') label(`label' `glabel') leftover(`r(leftover)')
	}
}

if "`size'" == "1" {
	di
	di in yell "`size'" in green " Solutions Entered as True"
	coverage `y' `sets' if `touse', orig(`orig') label(`label')
	local finsols `sets'
	}

return local reducsols `finsols'
return local y `y'
capture keep `vlist'
end

*Reduction Comparison*
capture program drop reduccomp
program define reduccomp, rclass
version 8.2
syntax anything
local cons `anything'
local con1: word 1 of `cons'
local con2: word 2 of `cons'
local numvars = length("`con1'")

local redcon
forvalues j = 1/`numvars' {
	local con1prt`j'= substr("`con1'", `j', 1)
	local con2prt`j'= substr("`con2'", `j', 1)
	if "`con1prt`j''" == "`con2prt`j''" {
		local redcon "`redcon' `con1prt`j''"
		}
	     else {
		local redcon "`redcon' -"
		}
	}
	return local redcon `redcon'
end