Skip to content

Commit

Permalink
version 0.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Jose R. Zubizarreta authored and cran-robot committed May 18, 2017
1 parent 207e5bb commit 75f738e
Show file tree
Hide file tree
Showing 14 changed files with 794 additions and 24 deletions.
16 changes: 7 additions & 9 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
Package: designmatch
Type: Package
Title: Construction of Optimally Matched Samples for Randomized
Experiments and Observational Studies that are Balanced and
Representative by Design
Version: 0.2.0
Date: 2016-08-09
Author: Jose R. Zubizarreta <[email protected]>, Cinar Kilcioglu <[email protected]>
Title: Matched Samples that are Balanced and Representative by Design
Version: 0.3.0
Date: 2017-05-17
Author: Jose R. Zubizarreta <[email protected]>, Cinar Kilcioglu <[email protected]>, Juan P. Vielma <[email protected]>
Maintainer: Jose R. Zubizarreta <[email protected]>
Depends: R (>= 3.2), lattice, MASS, slam, Rglpk
Suggests: gurobi, Rcplex, Rsymphony
SystemRequirements: GLPK library package (e.g., libglpk-dev on
Debian/Ubuntu)
License: GPL-2 | GPL-3
Description: Includes functions for the construction of matched samples that are balanced and representative by design. Among others, these functions can be used for matching in observational studies with treated and control units, with cases and controls, in related settings with instrumental variables, and in discontinuity designs. Also, they can be used for the design of randomized experiments, for example, for matching before randomization. By default, 'designmatch' uses the 'GLPK' optimization solver, but its performance is greatly enhanced by the 'Gurobi' optimization solver and its associated R interface. For their installation, please follow the instructions at http://user.gurobi.com/download/gurobi-optimizer and http://www.gurobi.com/documentation/6.5/refman/r_api_overview.html. We have also included directions in the gurobi_installation file in the inst folder.
Description: Includes functions for the construction of matched samples that are balanced and representative by design. Among others, these functions can be used for matching in observational studies with treated and control units, with cases and controls, in related settings with instrumental variables, and in discontinuity designs. Also, they can be used for the design of randomized experiments, for example, for matching before randomization. By default, 'designmatch' uses the 'GLPK' optimization solver, but its performance is greatly enhanced by the 'Gurobi' optimization solver and its associated R interface. For their installation, please follow the instructions at <http://user.gurobi.com/download/gurobi-optimizer> and <http://www.gurobi.com/documentation/7.0/refman/r_api_overview.html>. We have also included directions in the gurobi_installation file in the inst folder.
NeedsCompilation: no
Packaged: 2016-08-09 18:44:53 UTC; jrz
Packaged: 2017-05-18 01:39:38 UTC; jrz
Repository: CRAN
Date/Publication: 2016-08-11 13:01:07
Date/Publication: 2017-05-18 03:48:36 UTC
21 changes: 13 additions & 8 deletions MD5
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
3b16e7c71b53bcfd510a0b4c5467db3d *DESCRIPTION
e6ccf902847f31ee3b7a20750bbc8815 *DESCRIPTION
a84e461889448bab6f00dc036a173876 *NAMESPACE
4035589e4087aa8c0dfc97e90db340f8 *R/absstddif.R
4035589e4087aa8c0dfc97e90db340f8 *R/absstddif.r
7d1a85944bcd2594e3ab13ffdd80bd1e *R/addcalip.r
06d2cede573309b27980bbb8869ad01e *R/bmatch.r
932c4f0f192b4f4901220dcb169c4d50 *R/cardmatch.r
1ccbbc3d8e654fcd4366a8c93350178b *R/constraintmatrix.r
ddd36bec26100d3064a1bf106c36740c *R/distmat.R
f562ca6fc19a2951c9fcaaa01cae81dd *R/ecdfplot.R
ddd36bec26100d3064a1bf106c36740c *R/distmat.r
692b745a194a270376faf4842b958a02 *R/distmatch.r
f562ca6fc19a2951c9fcaaa01cae81dd *R/ecdfplot.r
d41d8cd98f00b204e9800998ecf8427e *R/errorhandling.r
a7c14294e78b350eca6b9b036f9f0817 *R/finetab.R
c98b06b08fd9add6edc0464b9d8d3443 *R/loveplot.R
d3df5386a7329cd2c93dedac69a83db4 *R/meantab.R
a7c14294e78b350eca6b9b036f9f0817 *R/finetab.r
c98b06b08fd9add6edc0464b9d8d3443 *R/loveplot.r
d3df5386a7329cd2c93dedac69a83db4 *R/meantab.r
4a4e30c24c6373c9118b32245b3f29fc *R/nmatch.r
98f291ae461a0b1c18ea5d8858b3eb22 *R/pairsplot.r
36d380e4bd2fb8bbd551af173cc12056 *R/problemparameters.r
3fc3b874e31fb6965591687cfc0481c9 *R/problemparameters_cardmatch.r
faaeb63e221a183bf338d8005151bb03 *R/relaxation_b.r
1ee8331d65f0dab43a41bd5a4740fcdf *R/relaxation_n.r
8a6974d5a5f551af3ca1e1be7d555be6 *R/smahal.r
0187616874e4a366b4ba006ded775e2d *data/germancities.rda
7c8f4dadefa6fd57a06a23067605dda0 *data/lalonde.rda
433defcdb5377aa4ebb28a0b41f492d7 *inst/gurobi_installation.txt
fca1c5c2ab15ec2207f7f77919cca494 *inst/gurobi_installation.txt
8b5ab702a3ca62c67934d34220c09ab6 *inst/symphony_installation.txt
a3432aa9ad196973c884751e3a7e0fb4 *man/absstddif.Rd
e19dd3ffc9a2b389b9ad4c0a7a082600 *man/bmatch.Rd
2f242dd6c23bbb2cf7b56ab900a74572 *man/cardmatch.Rd
70d7c69f620facbd7955281a7d6bbf1b *man/designmatch-package.Rd
9d510e34095ba20a26ae6ed0e3b7807a *man/distmat.Rd
90779867557e9b66310864ca76f825f5 *man/distmatch.Rd
60560ddae0cc24fb6cedc7785379fd3d *man/ecdfplot.Rd
093455696515de415adc6c394e839715 *man/finetab.Rd
3e98c15e211274459bbe5239f7342766 *man/germancities.Rd
Expand Down
File renamed without changes.
249 changes: 249 additions & 0 deletions R/cardmatch.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
#! cardmatch
cardmatch = function(t_ind, mom = NULL, fine = NULL, solver = NULL) {

if (is.null(mom)) {
mom_covs = NULL
mom_tols = NULL
mom_targets = NULL
} else {
mom_covs = mom$covs
mom_tols = mom$tols
mom_targets = mom$targets
}
if (is.null(fine)) {
fine_covs = NULL
} else {
fine_covs = fine$covs
}

if (is.null(solver)) {
solver = 'glpk'
t_max = 60 * 15
approximate = 1
} else {
t_max = solver$t_max
approximate = solver$approximate
trace = solver$trace
round_cplex = solver$round_cplex
solver = solver$name
}

#! CALL ERROR HANDLING

#! Generate the parameters
cat(format(" Building the matching problem..."), "\n")
prmtrs = .problemparameters_cardmatch(t_ind, mom_covs, mom_tols, mom_targets, fine_covs)
n_t = prmtrs$n_t
n_c = prmtrs$n_c
n_dec_vars = prmtrs$n_dec_vars
cvec = prmtrs$cvec
Amat = prmtrs$Amat
bvec = prmtrs$bvec
sense = prmtrs$sense
vtype = prmtrs$vtype

#! Find matches and calculate the elapsed time
#! Gurobi
if (solver == "gurobi") {
#library(gurobi)
if (requireNamespace('gurobi', quietly=TRUE)) {
cat(format(" Gurobi optimizer is open..."), "\n")
model = list()
model$modelsense = 'max'
model$obj = cvec
model$A = Amat
model$sense = rep(NA, length(sense))
model$sense[sense=="E"] = '='
model$sense[sense=="L"] = '<='
model$sense[sense=="G"] = '>='
model$rhs = bvec
model$vtypes = vtype

t_lim = list(TimeLimit = t_max, OutputFlag = trace)

cat(format(" Finding the optimal matches..."), "\n")
ptm = proc.time()
out = gurobi::gurobi(model, t_lim)
time = (proc.time()-ptm)[3]

if (out$status == "INFEASIBLE") {
cat(format(" Error: problem infeasible!"), "\n")
obj_total = NA
obj_dist_mat = NA
t_id = NA
c_id = NA
group_id = NA
time = NA
}

if (out$status == "OPTIMAL" || out$status == "TIME_LIMIT") {
if (out$status == "OPTIMAL") {
cat(format(" Optimal matches found"), "\n")
}

else {
cat(format(" Time limit reached, best suboptimal solution given"), "\n")
}

#! Matched units indexes
t_id = (1:n_dec_vars)[t_ind==1 & out$x==1]
c_id = (1:n_dec_vars)[t_ind==0 & out$x==1]

#! Group (or pair) identifier
group_id = c(1:(length(t_id)), 1:(length(c_id)))

#! Optimal value of the objective function
obj_total = out$objval
}
} else {
stop('Required solver not installed')
}

}

#! CPLEX
else if (solver == "cplex") {
#library(Rcplex)
if (requireNamespace('Rcplex', quietly=TRUE)) {
cat(format(" CPLEX optimizer is open..."), "\n")
cat(format(" Finding the optimal matches..."), "\n")
ptm = proc.time()
out = Rcplex::Rcplex(objsense = 'max', cvec, Amat, bvec, sense = sense, vtype = vtype, n = 1,
control = list(trace = trace, round = round_cplex, tilim = t_max))
time = (proc.time()-ptm)[3]

if (out$status==108) {
cat(format(" Error: time limit exceeded, no integer solution!"), "\n")
obj_total = NA
obj_dist_mat = NA
t_id = NA
c_id = NA
group_id = NA
time = NA
} else if (is.na(out$obj)) {
cat(format(" Error: problem infeasible!"), "\n")
obj_total = NA
obj_dist_mat = NA
t_id = NA
c_id = NA
group_id = NA
time = NA
}

if (!is.na(out$obj)) {
cat(format(" Optimal matches found"), "\n")

#! Matched units indexes
t_id = (1:n_dec_vars)[t_ind==1 & out$xopt==1]
c_id = (1:n_dec_vars)[t_ind==0 & out$xopt==1]

#! Group (or pair) identifier
group_id = c(1:(length(t_id)), 1:(length(c_id)))

#! Optimal value of the objective function
obj_total = out$obj

}
} else {
stop('Required solver not installed')
}

}

#! GLPK
else if (solver == "glpk") {
#library(Rglpk)
cat(format(" GLPK optimizer is open..."), "\n")
dir = rep(NA, length(prmtrs$sense))
dir[prmtrs$sense=="E"] = '=='
dir[prmtrs$sense=="L"] = '<='
dir[prmtrs$sense=="G"] = '>='

cat(format(" Finding the optimal matches..."), "\n")
ptm = proc.time()
out= Rglpk_solve_LP(cvec, Amat, dir, bvec, types = vtype, max = TRUE)
time = (proc.time()-ptm)[3]

if (out$status!=0) {
cat(format(" Error: problem infeasible!"), "\n")
obj_total = NA
obj_dist_mat = NA
t_id = NA
c_id = NA
group_id = NA
time = NA
}

if (out$status==0) {
cat(format(" Optimal matches found"), "\n")

#! Matched units indexes
t_id = (1:n_dec_vars)[t_ind==1 & out$solution==1]
c_id = (1:n_dec_vars)[t_ind==0 & out$solution==1]

#! Group (or pair) identifier
group_id = c(1:(length(t_id)), 1:(length(c_id)))

#! Optimal value of the objective function
obj_total = out$optimum

}
}

#! Symphony
else {
#library(Rsymphony)
if (requireNamespace('Rsymphony', quietly=TRUE)) {
cat(format(" Symphony optimizer is open..."), "\n")

dir = rep(NA, length(prmtrs$sense))
dir[prmtrs$sense=="E"] = '=='
dir[prmtrs$sense=="L"] = '<='
dir[prmtrs$sense=="G"] = '>='

cat(format(" Finding the optimal matches..."), "\n")
ptm = proc.time()
out= Rsymphony::Rsymphony_solve_LP(cvec, Amat, dir, bvec, types = vtype, max = TRUE, time_limit = t_max)
time = (proc.time()-ptm)[3]

if (out$status==228) {
cat(format(" Error: problem exceeded the time limit and no feasible solution is found!"), "\n")
obj_total = NA
obj_dist_mat = NA
t_id = NA
c_id = NA
group_id = NA
time = NA
}
else if (out$status!=0) {
cat(format(" Error: problem infeasible!"), "\n")
obj_total = NA
obj_dist_mat = NA
t_id = NA
c_id = NA
group_id = NA
time = NA
}

if (out$status==0) {
cat(format(" Optimal matches found"), "\n")

#! Matched units indexes
t_id = (1:n_dec_vars)[t_ind==1 & out$solution==1]
c_id = (1:n_dec_vars)[t_ind==0 & out$solution==1]

#! Group (or pair) identifier
group_id = c(1:(length(t_id)), 1:(length(c_id)))

#! Optimal value of the objective function
obj_total = out$objval

}
} else {
stop('Required solver not installed')
}

}
#! Output
return(list(obj_total = obj_total, t_id = t_id, c_id = c_id, group_id = group_id, time = time))
}
File renamed without changes.
17 changes: 17 additions & 0 deletions R/distmatch.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#! distmatch
distmatch = function(t_ind, dist_mat = NULL, solver = NULL) {

# Subset matching weight
subset_weight = 0

# Total number of matched pairs
total_groups = sum(t_ind)

# Match
out = bmatch(t_ind = t_ind, dist_mat = dist_mat, subset_weight = subset_weight, total_groups = total_groups, solver = solver)

#! Output
return(list(obj_total = out$obj_total, obj_dist_mat = out$obj_dist_mat,
t_id = out$t_id, c_id = out$c_id, group_id = out$group_id, time = out$time, status = out$status))

}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 75f738e

Please sign in to comment.