Skip to content

Commit 664c0c7

Browse files
committed
Placed non-negativity constraint enforcement in correct place this time; updated some tests that were checking for exact equality to zero
1 parent c36f04b commit 664c0c7

File tree

2 files changed

+44
-44
lines changed

2 files changed

+44
-44
lines changed

R/multi_synth_qp.R

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,6 @@ multisynth_qp <- function(X, trt, mask, Z = NULL, n_leads=NULL, n_lags=NULL,
155155
## get weights
156156
total_ctrls <- n0 * J
157157
weights <- matrix(out$x[1:total_ctrls], nrow = n0)
158-
# manually enforce non-negativity constraint
159-
# (osqp solver only enforces constraint up to a tolerance)
160-
weights <- pmax(weights, 0)
161158
nj0 <- as.numeric(lapply(Xc, nrow))
162159
nj0cumsum <- c(0, cumsum(nj0))
163160
imbalance <- vapply(1:J,
@@ -192,6 +189,9 @@ multisynth_qp <- function(X, trt, mask, Z = NULL, n_leads=NULL, n_lags=NULL,
192189
numeric(n)) -> weights
193190

194191
weights <- t(t(weights) / n1)
192+
# manually enforce non-negativity constraint
193+
# (osqp solver only enforces constraint up to a tolerance)
194+
weights <- pmax(weights, 0)
195195

196196
output <- list(weights = weights,
197197
imbalance = cbind(avg_imbal, imbalance),

tests/testthat/test_multisynth_covariates.R

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,20 @@ test_that("Getting eligible donor units by exact matching works", {
2828
scm = T)
2929

3030
# check that there is actually no weight on donors with different Z
31-
expect_equal(sum(msyn$weights[fake_bin == 1, 1]), 1, tolerance = 1e-6)
32-
expect_equal(sum(msyn$weights[fake_bin == 0, 1]), 0, tolerance = 1e-6)
33-
expect_equal(sum(msyn$weights[fake_bin == 1, 2]), 0, tolerance = 1e-6)
34-
expect_equal(sum(msyn$weights[fake_bin == 0, 2]), 1, tolerance = 1e-6)
31+
expect_equal(sum(msyn$weights[fake_bin == 1, 1]), 1, tolerance = 1e-4)
32+
expect_equal(sum(msyn$weights[fake_bin == 0, 1]), 0, tolerance = 1e-4)
33+
expect_equal(sum(msyn$weights[fake_bin == 1, 2]), 0, tolerance = 1e-4)
34+
expect_equal(sum(msyn$weights[fake_bin == 0, 2]), 1, tolerance = 1e-3)
3535

3636

3737
# again with fixed effect
3838
msyn <- multisynth(gdpcap ~ trt | 0 | 0 | Z, regionno, year, basque2, nu = 0,
3939
scm = T, fixedeff = T)
4040
# check that there is actually no weight on donors with different Z
41-
expect_equal(sum(msyn$weights[fake_bin == 1, 1]), 1, tolerance = 1e-6)
42-
expect_equal(sum(msyn$weights[fake_bin == 0, 1]), 0, tolerance = 1e-6)
43-
expect_equal(sum(msyn$weights[fake_bin == 1, 2]), 0, tolerance = 1e-6)
44-
expect_equal(sum(msyn$weights[fake_bin == 0, 2]), 1, tolerance = 1e-6)
41+
expect_equal(sum(msyn$weights[fake_bin == 1, 1]), 1, tolerance = 1e-4)
42+
expect_equal(sum(msyn$weights[fake_bin == 0, 1]), 0, tolerance = 1e-4)
43+
expect_equal(sum(msyn$weights[fake_bin == 1, 2]), 0, tolerance = 1e-4)
44+
expect_equal(sum(msyn$weights[fake_bin == 0, 2]), 1, tolerance = 1e-3)
4545
})
4646

4747
test_that("Getting eligible donor units by exact matching works with factors", {
@@ -63,24 +63,24 @@ test_that("Getting eligible donor units by exact matching works with factors", {
6363
scm = T)
6464

6565
# check that there is actually no weight on donors with different Z
66-
expect_equal(sum(msyn$weights[fake_fac == 1, 1]), 1, tolerance = 1e-6)
67-
expect_equal(sum(msyn$weights[fake_fac == 0, 1]), 0, tolerance = 1e-6)
68-
expect_equal(sum(msyn$weights[fake_fac == 3, 1]), 0, tolerance = 1e-6)
69-
expect_equal(sum(msyn$weights[fake_fac == 1, 2]), 0, tolerance = 1e-6)
70-
expect_equal(sum(msyn$weights[fake_fac == 0, 2]), 1, tolerance = 1e-6)
71-
expect_equal(sum(msyn$weights[fake_fac == 3, 2]), 0, tolerance = 1e-6)
66+
expect_equal(sum(msyn$weights[fake_fac == 1, 1]), 1, tolerance = 1e-4)
67+
expect_equal(sum(msyn$weights[fake_fac == 0, 1]), 0, tolerance = 1e-4)
68+
expect_equal(sum(msyn$weights[fake_fac == 3, 1]), 0, tolerance = 1e-4)
69+
expect_equal(sum(msyn$weights[fake_fac == 1, 2]), 0, tolerance = 1e-4)
70+
expect_equal(sum(msyn$weights[fake_fac == 0, 2]), 1, tolerance = 1e-4)
71+
expect_equal(sum(msyn$weights[fake_fac == 3, 2]), 0, tolerance = 1e-4)
7272

7373

7474
# again with fixed effect
7575
msyn <- multisynth(gdpcap ~ trt | 0 | 0 |Z, regionno, year, basque2, nu = 0,
7676
scm = T, fixedeff = T, how_match = "exact")
7777
# check that there is actually no weight on donors with different Z
78-
expect_equal(sum(msyn$weights[fake_fac == 1, 1]), 1, tolerance = 1e-6)
79-
expect_equal(sum(msyn$weights[fake_fac == 0, 1]), 0, tolerance = 1e-6)
80-
expect_equal(sum(msyn$weights[fake_fac == 3, 1]), 0, tolerance = 1e-6)
81-
expect_equal(sum(msyn$weights[fake_fac == 1, 2]), 0, tolerance = 1e-6)
82-
expect_equal(sum(msyn$weights[fake_fac == 0, 2]), 1, tolerance = 1e-6)
83-
expect_equal(sum(msyn$weights[fake_fac == 3, 2]), 0, tolerance = 1e-6)
78+
expect_equal(sum(msyn$weights[fake_fac == 1, 1]), 1, tolerance = 1e-4)
79+
expect_equal(sum(msyn$weights[fake_fac == 0, 1]), 0, tolerance = 1e-4)
80+
expect_equal(sum(msyn$weights[fake_fac == 3, 1]), 0, tolerance = 1e-4)
81+
expect_equal(sum(msyn$weights[fake_fac == 1, 2]), 0, tolerance = 1e-4)
82+
expect_equal(sum(msyn$weights[fake_fac == 0, 2]), 1, tolerance = 1e-4)
83+
expect_equal(sum(msyn$weights[fake_fac == 3, 2]), 0, tolerance = 1e-4)
8484
})
8585

8686
test_that("K-NN finds the right number of neighbors", {
@@ -124,29 +124,29 @@ test_that("Getting eligible donor units by knn matching works", {
124124
msyn <- multisynth(gdpcap ~ trt | 0 | Z1 + Z2 + Z3, regionno, year,
125125
basque2, scm = T, how_match = "knn", k = k)
126126

127-
# check that all but k units recieve exactly 0 weight
128-
expect_equal(sum(msyn$weights[, 1] != 0), k, tolerance = 1e-12)
129-
expect_equal(sum(msyn$weights[, 2] != 0), k, tolerance = 1e-12)
127+
# check that at most k units recieve non-0 weight
128+
expect_lte(sum(msyn$weights[, 1] != 0), k)
129+
expect_lte(sum(msyn$weights[, 2] != 0), k)
130130

131131

132132

133133
# again with fixed effect
134134
msyn <- multisynth(gdpcap ~ trt | 0 | Z1 + Z2 + Z3, regionno, year,
135135
basque2, scm = T, fixedeff = T, how_match = "knn", k = k)
136136
# check that all but k units recieve exactly 0 weight
137-
expect_equal(sum(msyn$weights[, 1] != 0), k, tolerance = 1e-12)
138-
expect_equal(sum(msyn$weights[, 2] != 0), k, tolerance = 1e-12)
137+
expect_lte(sum(msyn$weights[, 1] != 0), k)
138+
expect_lte(sum(msyn$weights[, 2] != 0), k)
139139

140140
# without synth weights, weights are uniform
141141
k <- 2
142-
unimatch <- multisynth(gdpcap ~ trt| 0 | Z1 + Z2 + Z3 | 0, regionno, year,
142+
unimatch <- multisynth(gdpcap ~ trt| 0 | Z1 + Z2 + Z3, regionno, year,
143143
basque2, scm = T, how_match = "knn", k = k, lambda = 1e10)
144144

145145
expect_equal(unimatch$weights[unimatch$weights != 0 ], rep(1 / k, 2 * k))
146146

147147
# matching with more neighbors is worse
148148
unimatch2 <- multisynth(gdpcap ~ trt | 0 | Z1 + Z2 + Z3, regionno, year, basque2,
149-
scm = T, how_match = "knn", k = 2 * k, lambda = 1e10)
149+
scm = T, how_match = "knn", k = 2.5 * k, lambda = 1e10)
150150

151151
trtZ <- Z[regions %in% c(16, 17),]
152152
imbal1 <- sqrt(sum(sapply(1:2,
@@ -187,27 +187,27 @@ test_that("Getting eligible donor units by exact and knn matching works", {
187187
basque2, scm = T, how_match = "knn", k = k)
188188

189189
# check that there is actually no weight on donors with different Z
190-
expect_equal(sum(msyn$weights[fake_bin == 1, 1]), 1, tolerance = 1e-6)
191-
expect_equal(sum(msyn$weights[fake_bin == 0, 1]), 0, tolerance = 1e-6)
192-
expect_equal(sum(msyn$weights[fake_bin == 1, 2]), 0, tolerance = 1e-6)
193-
expect_equal(sum(msyn$weights[fake_bin == 0, 2]), 1, tolerance = 1e-6)
190+
expect_equal(sum(msyn$weights[fake_bin == 1, 1]), 1, tolerance = 1e-4)
191+
expect_equal(sum(msyn$weights[fake_bin == 0, 1]), 0, tolerance = 1e-4)
192+
expect_equal(sum(msyn$weights[fake_bin == 1, 2]), 0, tolerance = 1e-4)
193+
expect_equal(sum(msyn$weights[fake_bin == 0, 2]), 1, tolerance = 1e-4)
194194

195-
# check that all but k units recieve exactly 0 weight
196-
expect_equal(sum(msyn$weights[, 1] != 0), k, tolerance = 1e-12)
197-
expect_equal(sum(msyn$weights[, 2] != 0), k, tolerance = 1e-12)
195+
# check that at most k units recieve non-0 weight
196+
expect_lte(sum(msyn$weights[, 1] != 0), k)
197+
expect_lte(sum(msyn$weights[, 2] != 0), k)
198198

199199
# again with fixed effect
200200
msyn <- multisynth(gdpcap ~ trt | 0 | Z1 + Z2 + Z3 | Z_bin, regionno, year,
201201
basque2, scm = T, fixedeff = T, how_match = "knn", k = k)
202-
# check that all but k units recieve exactly 0 weight
203-
expect_equal(sum(msyn$weights[, 1] != 0), k, tolerance = 1e-12)
204-
expect_equal(sum(msyn$weights[, 2] != 0), k, tolerance = 1e-12)
202+
# check that at most k units recieve non-0 weight
203+
expect_lte(sum(msyn$weights[, 1] != 0), k)
204+
expect_lte(sum(msyn$weights[, 2] != 0), k)
205205

206206
# check that there is actually no weight on donors with different Z
207-
expect_equal(sum(msyn$weights[fake_bin == 1, 1]), 1, tolerance = 1e-6)
208-
expect_equal(sum(msyn$weights[fake_bin == 0, 1]), 0, tolerance = 1e-6)
209-
expect_equal(sum(msyn$weights[fake_bin == 1, 2]), 0, tolerance = 1e-6)
210-
expect_equal(sum(msyn$weights[fake_bin == 0, 2]), 1, tolerance = 1e-6)
207+
expect_equal(sum(msyn$weights[fake_bin == 1, 1]), 1, tolerance = 1e-4)
208+
expect_equal(sum(msyn$weights[fake_bin == 0, 1]), 0, tolerance = 1e-4)
209+
expect_equal(sum(msyn$weights[fake_bin == 1, 2]), 0, tolerance = 1e-4)
210+
expect_equal(sum(msyn$weights[fake_bin == 0, 2]), 1, tolerance = 1e-4)
211211

212212
k <- 3
213213
# without synth weights, weights are uniform

0 commit comments

Comments
 (0)