*! Date : 08 May 2018 *! Version : 1.0 /* 08/05/18 v1.0 Initial version complete */ program define des_fixed, rclass version 11.0 syntax, [pi0(real 0.1) pi1(real 0.3) Alpha(real 0.05) Beta(real 0.2) /// nmin(integer 1) nmax(integer 30) EXact(integer 1) /// SUMmary(integer 0) PLot *] local xopt `"`options'"' preserve ///// Perform checks on input variables //////////////////////////////////////// if ((`pi0' <= 0) | (`pi0' >= 1)) { di "{error} pi0 must be a real strictly between 0 and 1." exit(198) } if ((`pi1' <= 0) | (`pi1' >= 1)) { di "{error} pi1 must be a real strictly between 0 and 1." exit(198) } if (`pi0' >= `pi1') { di "{error} pi0 must be a real strictly less than the real pi1." exit(198) } if ((`alpha' <= 0) | (`alpha' >= 1)) { di "{error} alpha must be a real strictly between 0 and 1." exit(198) } if ((`beta' <= 0) | (`beta' >= 1)) { di "{error} beta must be a real strictly between 0 and 1." exit(198) } if (`nmin' <= 0) { di "{error} nmin must be a strictly positive integer." exit(198) } if (`nmax' <= 0) { di "{error} nmax must be a strictly positive integer." exit(198) } if (`nmin' > `nmax') { di "{error} nmin must be an integer less than or equal to the integer nmax." exit(198) } ///// Compute and Output /////////////////////////////////////////////////////// mata: DesFixed(`pi0', `pi1', `alpha', `beta', `nmin', `nmax', `exact', `summary', "`plot'", `"`xopt'"') matrix rownames des = "Optimal design" matrix colnames des = n a r "P(pi0)" "P(pi1)" return mat des = des return mat n = n return mat a = a return mat r = r matrix colnames feasible = n a r "P(pi0)" "P(pi1)" return mat feasible = feasible return mat pi0 = pi0 return mat pi1 = pi1 return mat alpha = alpha return mat beta = beta return mat nmin = Nmin return mat nmax = Nmax return mat exact = exact return mat summary = summary restore end ///// Mata //////////////////////////////////////////////////////////////////// mata: void DesFixed(pi0, pi1, alpha, beta, Nmin, Nmax, exact, summary, plot, xopt) { ///// Print Summary ////////////////////////////////////////////////////////// ///// Main Computations ////////////////////////////////////////////////////// dbinomial_pi0 = J(Nmax + 1, Nmax, 0) dbinomial_pi1 = J(Nmax + 1, Nmax, 0) for (i = 1; i <= Nmax; i++) { dbinomial_pi0[1::(i + 1), i] = binomialp(i, 0::i, pi0) dbinomial_pi1[1::(i + 1), i] = binomialp(i, 0::i, pi1) } if (exact == 1) { possible = permutations(0::Nmax, 2) possible = possible[mm_which(possible[, 1] :> possible[, 2] :& 0 :< possible[, 1]), ] } else { possible = Nmin::Nmax possible = (possible, round(possible*pi0 + invnormal(1 - alpha)*sqrt(possible*pi0*(1 - pi0)))) possible = possible[mm_which(possible[, 1] :> possible[, 2] :& 0 :<= possible[, 2]), ] } possible = (possible, possible[, 2] + J(rows(possible), 1, 1), J(rows(possible), 2, 0)) for (i = 1; i <= rows(possible); i++) { possible[i, (4, 5)] = (sum(dbinomial_pi0[(possible[i, 3] + 1)::possible[i, 1], possible[i, 1]]), sum(dbinomial_pi1[(possible[i, 3] + 1)::possible[i, 1], possible[i, 1]])) if (allof((summary == 1, mod(i, 1000) == 0), 1)) { printf("{txt}...{res}%g{txt} designs evaluated...\n", i) } } if (summary == 1) { printf("...determining feasible designs, and then the optimal design...") } feasible = possible[mm_which(possible[, 4] :<= alpha :& possible[, 5] :>= 1 - beta), ] if (rows(feasible) > 0) { feasible = sort(feasible, (1, -5)) des = feasible[1, ] n = feasible[1, 1] a = feasible[1, 2] r = feasible[1, 3] if (plot ~= "") { states_cont = permutations(0::(n - 1), 2) states_cont = states_cont[mm_which((states_cont[, 1] :<= states_cont[, 2]) :& (states_cont[, 2] :> 0)), ] states_acc = ((0::a), J(a + 1, 1, n)) states_rej = ((r::n), J(n - r + 1, 1, n)) st_matrix("states_cont", states_cont) st_matrix("states_acc", states_acc) st_matrix("states_rej", states_rej) stata("qui svmat states_cont") stata("qui svmat states_acc") stata("qui svmat states_rej") stata(`"twoway (scatter states_cont1 states_cont2, msymbol(oh) color(gs13)) (scatter states_acc1 states_acc2, msymbol(X) color(red)) (scatter states_rej1 states_rej2, msymbol(+) color(green)), xtitle({it:s}) ytitle({it:m}) legend(lab(1 "Continue") lab(2 "Do not reject {it:H}{subscript:0}") lab(3 "Reject {it:H}{subscript:0}"))"'+ xopt) } } else { feasible = des = J(1, 5, .) n = a = r = . } ///// Return ///////////////////////////////////////////////////////////////// if (summary == 1) { printf("...outputting") } st_matrix("des", des) st_matrix("n", n) st_matrix("a", a) st_matrix("r", r) st_matrix("feasible", feasible) st_matrix("pi0", pi0) st_matrix("pi1", pi1) st_matrix("alpha", alpha) st_matrix("beta", beta) st_matrix("Nmin", Nmin) st_matrix("Nmax", Nmax) st_matrix("exact", exact) st_matrix("summary", summary) } // Function to determine all permutations of length q from a vector vec with // replacement real matrix permutations(real colvector vec, real scalar q) { if (q == 1) { return(vec) } lvec = length(vec) if (lvec == 1) { return(J(1, q, vec)) } l = lvec^q allperms = J(l, q, 0) d = vec[2::lvec] :- vec[1::(lvec - 1)] ld = length(d) vl = (-sum(d) \ d) tmp = J(1, l/lvec, vl) allperms[1::l, q] = vec(tmp) elts = 1 count = 1 while (elts[count] + lvec^(q - 1) <= l) { elts = (elts \ elts[count] + lvec^(q - 1)) count = count + 1 } allperms[elts, 1] = vl if (q > 2) { for (i = 2; i <= q - 1; i++) { elts = 1 count = 1 while (elts[count] + lvec^(i - 1) <= l) { elts = (elts \ elts[count] + lvec^(i - 1)) count = count + 1 } tmp = J(1, length(elts)/(ld + 1), vl) allperms[elts, q - i + 1] = vec(tmp) } } allperms[1, 1::q] = J(1, q, vec[1]) origallperms = allperms for (i = 2; i <= l; i++) { for (j = 1; j <= q; j++) { allperms[i, j] = sum(origallperms[1::i, j]) } } return(allperms) } end