Nothing
#' @aliases get.sdcProblem,sdcProblem,character-method
#' @rdname get.sdcProblem-method
setMethod(f="get.sdcProblem", signature=c("sdcProblem", "character"),
definition=function(object, type) {
poss <- c("dataObj", "problemInstance", "partition", "dimInfo", "indicesDealtWith",
"startI", "startJ", "innerAndMarginalCellInfo")
if (!type %in% poss) {
err <- c(
"get.sdcProblem:: argument 'type' is not valid. possible chocices are: ", paste(shQuote(poss), collapse = ", ")
)
stop(paste(err, collapse = "\n"), call. = FALSE)
}
if (type == "dataObj") {
return(g_dataObj(object))
}
if (type == "problemInstance") {
return(g_problemInstance(object))
}
if (type == "partition") {
return(g_partition(object))
}
if (type == "dimInfo") {
return(g_dimInfo(object))
}
if (type == "indicesDealtWith") {
return(g_indicesDealtWith(object))
}
if (type == "startI") {
return(g_startI(object))
}
if (type == "startJ") {
return(g_startJ(object))
}
if (type == "innerAndMarginalCellInfo") {
return(g_innerAndMarginalCellInfo(object))
}
}
)
#' @aliases set.sdcProblem,sdcProblem,character,list-method
#' @rdname set.sdcProblem-method
setMethod(f = "set.sdcProblem",
signature = c("sdcProblem", "character", "list"),
definition = function(object, type, input) {
if (!type %in% c(
"problemInstance",
"partition",
"rule.freq",
"startI",
"startJ",
"indicesDealtWith"
)) {
stop("set.sdcProblem:: check argument 'type'!\n")
}
if (type == "problemInstance") {
s_problemInstance(object) <- input[[1]]
}
if (type == "partition") {
s_partition(object) <- input[[1]]
}
if (type == "startI") {
s_startI(object) <- input[[1]]
}
if (type == "startJ") {
s_startJ(object) <- input[[1]]
}
if (type == "indicesDealtWith") {
s_indicesDealtWith(object) <- input[[1]]
}
validObject(object)
return(object)
})
#' @aliases calc.sdcProblem,sdcProblem,character,list-method
#' @rdname calc.sdcProblem-method
setMethod(f="calc.sdcProblem", signature=c("sdcProblem", "character", "list"),
definition=function(object, type, input) {
if ( !type %in% c("rule.freq", "heuristicSolution",
"cutAndBranch", "anonWorker", "ghmiter", "preprocess", "cellID",
"finalize", "ghmiter.diagObj", "ghmiter.calcInformation",
"ghmiter.suppressQuader", "ghmiter.selectQuader",
"ghmiter.suppressAdditionalQuader",
"reduceProblem", "genStructuralCuts") ) {
stop("calc.sdcProblem:: check argument 'type'!\n")
}
# frequency-rule
if (type == "rule.freq") {
return(c_rule_freq(object, input))
}
if (type == "heuristicSolution") {
return(c_heuristic_solution(object, input))
}
if (type == "cutAndBranch") {
return(c_cut_and_branch(object, input))
}
if (type == "anonWorker") {
return(c_anon_worker(object, input))
}
if (type == "ghmiter") {
return(c_ghmiter(object, input))
}
if (type == "preprocess") {
return(c_preprocess(object, input))
}
if (type == "finalize") {
return(c_finalize(object, input))
}
if (type == "ghmiter.diagObj") {
return(c_ghmiter_diag_obj(object, input))
}
if (type == "ghmiter.calcInformation") {
return(c_ghmiter_calc_info(object, input))
}
if (type == "ghmiter.suppressQuader") {
return(c_ghmiter_suppress_quader(object, input))
}
if (type == "ghmiter.selectQuader") {
return(c_ghmiter_select_quader(object, input))
}
if (type == "ghmiter.suppressAdditionalQuader") {
return(c_ghmiter_supp_additional(object, input))
}
if (type == "reduceProblem") {
return(c_reduce_problem(object, input))
}
if (type == "genStructuralCuts") {
return(c_gen_structcuts(object, input))
}
}
)
#' summarize object of class \code{\link{sdcProblem-class}} or \code{\link{safeObj-class}}.
#'
#' extract and show relevant information stored in object ofs class \code{\link{sdcProblem-class}} or \code{\link{safeObj-class}}.
#'
#' @aliases summary,sdcProblem-method
#' @rdname summary.sdcProblem-method
#' @param object Objects of either class \code{\link{sdcProblem-class}} or \code{\link{safeObj-class}}.
#' @param ... currently not used.
#' @export
#' @docType methods
setMethod(f="summary", signature="sdcProblem",
definition = function(object, ...) {
if (!is.null(object@results)) {
summarize_safeobj(object = object, ...)
return(invisible(NULL))
}
pI <- g_problemInstance(object)
dO <- g_dataObj(object)
dI <- g_dimInfo(object)
if (g_is_microdata(dO)) {
cat("The raw data contains micro data!")
if (length(pI@numVars) > 0) {
cat("--> the use of dominance rules for primary suppressions is possible!")
}
cat("\n")
} else {
cat("The raw data contain pre-aggregated (tabular) data!\n")
}
nrcells <- g_nrVars(pI)
dim_names <- g_varname(dI)
cat("\nThe complete table to protect consists of",nrcells,"cells and has",length(dim_names),"spanning variables.")
cat("\nThe distribution of\n")
cat("- primary unsafe (u)\n")
cat("- secondary suppressed (x)\n")
cat("- forced to publish (z) and\n")
cat("- selectable for secondary suppression (s) cells is shown below:\n")
print(table(g_sdcStatus(pI)))
nr_tables <- g_partition(object)$nrTables
cat("\nIf this table is protected with heuristic methods, a total of",nr_tables,"has (sub)tables must be considered!\n")
}
)
#' print objects of class \code{\link{sdcProblem-class}}.
#'
#' print some useful information instead of just displaying the entire object (which may be large)
#'
#' @aliases print,sdcProblem-method
#' @rdname print.sdcProblem-method
#' @param x an objects of class \code{\link{sdcProblem-class}}
#' @param ... currently not used.
#' @export
#' @docType methods
setMethod("print", signature="sdcProblem",
definition=function(x, ...) {
dims <- x@dimInfo@dimInfo
nr_dims <- length(dims)
nr_cells <- length(x@problemInstance@strID)
is_protected <- !is.null(x@results)
message(paste("The object is a sdcProblem instance with", nr_cells, "cells in", nr_dims, "dimension(s)!"))
if (is_protected) {
message(paste0("Protection: yes (using ", shQuote(attributes(x@results)$supp_method), ")"))
} else {
message("Protection: no")
}
message("\nThe dimensions are:")
for (i in 1:nr_dims) {
nr_codes <- length(dims[[i]]@codesOriginal)
nr_aggregates <- sum(dims[[i]]@codesMinimal == FALSE)
max_hier <- length(dims[[i]]@structure)
message(paste0("\t- ", names(dims)[i]," (", max_hier," levels; ", nr_codes," codes; of these being ", nr_aggregates," aggregates)"))
}
if (is_protected) {
message("\nSuppression pattern:")
sdc_status <- x@results$sdcStatus
} else {
message("\nCurrent suppression pattern:")
sdc_status <- x@problemInstance@sdcStatus
}
message("\t- Primary suppressions: ", sum(sdc_status == "u"))
message("\t- Secondary suppressions: ", sum(sdc_status == "x"))
message("\t- Publishable cells: ", sum(sdc_status %in% c("s","z")))
}
)
#' show objects of class \code{\link{sdcProblem-class}}.
#'
#' just calls the corresponding print-method
#'
#' @aliases show,sdcProblem-method
#' @rdname show.sdcProblem-method
#' @param object an objects of class \code{\link{sdcProblem-class}}
#' @export
#' @docType methods
setMethod("show", signature="sdcProblem",
definition=function(object) {
print(object)
}
)
setMethod("g_problemInstance", signature="sdcProblem", definition=function(object) {
object@problemInstance
})
setMethod("g_dimInfo", signature="sdcProblem", definition=function(object) {
object@dimInfo
})
setMethod("g_partition", signature="sdcProblem", definition=function(object) {
object@partition
})
setMethod("g_dataObj", signature="sdcProblem", definition=function(object) {
object@dataObj
})
setMethod("g_startI", signature="sdcProblem", definition=function(object) {
object@startI
})
setMethod("g_startJ", signature="sdcProblem", definition=function(object) {
object@startJ
})
setMethod("g_indicesDealtWith", signature="sdcProblem", definition=function(object) {
object@indicesDealtWith
})
setMethod("g_innerAndMarginalCellInfo", signature="sdcProblem", definition=function(object) {
pI <- g_problemInstance(object)
strIDs <- g_strID(pI)
strInfo <- g_str_info(g_dimInfo(object))
out <- lapply(1:length(strInfo), function(x) {
sort(unique(mySplit(strIDs, strInfo[[x]][1]:strInfo[[x]][2])))[-1]
})
# deal with 'tot' levels
ind <- which(sapply(out, length) ==0)
out[ind] <- lapply(ind, function(x) { "0" } )
innerCells <- apply(matrix(unlist(expand(out)), ncol=length(out), byrow=FALSE),1,paste, collapse="")
totCells <- setdiff(strIDs, innerCells)
indexTotCells <- match(totCells, strIDs)
indexInnerCells <- match(innerCells, strIDs)
return(list(innerCells=innerCells, totCells=totCells, indexInnerCells=indexInnerCells, indexTotCells=indexTotCells))
})
setMethod("g_df", signature="sdcProblem", definition=function(object, addDups=FALSE, addNumVars=FALSE) {
xx <- strID <- NULL
pI <- g_problemInstance(object)
dt <- data.table(
strID=g_strID(pI),
freq=g_freq(pI),
sdcStatus=g_sdcStatus(pI))
if (addNumVars & !is.null(pI@numVars)) {
dt <- cbind(dt, as.data.table(pI@numVars))
}
dI <- g_dimInfo(object)
strInfo <- g_str_info(dI)
dimObj <- g_dim_info(dI)
vNames <- g_varname(dI)
res <- as.data.table(cpp_splitByIndices(g_strID(pI), strInfo))
setnames(res, vNames)
dt <- cbind(dt, res)
for ( i in 1:length(strInfo) ) {
v <- paste0(vNames[i],"_o",sep="")
dt[[v]] <- c_match_orig_codes(object=dimObj[[i]], input=dt[[vNames[i]]])
}
if ( addDups ) {
dims <- g_dim_info(dI)
for ( i in seq_along(dims) ) {
if ( g_has_dups(dims[[i]]) ) {
dU <- dims[[i]]@dupsUp
dL <- dims[[i]]@dups
vName <- paste0(dims[[i]]@vName,"_o")
for ( j in 1:length(dL) ) {
cmd <- paste0("xx <- dt[",vName,"=='",dU[j],"']")
eval(parse(text=cmd))
if ( !is.numeric(dt[[vName]]) ) {
cmd <- paste0("xx[,",vName,":='",dL[j],"']")
} else {
cmd <- paste0("xx[,",vName,":=",dL[j],"]")
}
eval(parse(text=cmd))
dt <- rbind(dt, xx); rm(xx)
}
}
}
}
setkey(dt, strID)
return(dt)
})
setReplaceMethod("s_problemInstance", signature=c("sdcProblem", "problemInstance"), definition=function(object, value) {
object@problemInstance <- value
validObject(object)
object
})
setReplaceMethod("s_partition", signature=c("sdcProblem"), definition=function(object, value) {
object@partition <- value
validObject(object)
object
})
setReplaceMethod("s_startI", signature=c("sdcProblem", "numeric"), definition=function(object, value) {
object@startI <- value
validObject(object)
object
})
setReplaceMethod("s_startJ", signature=c("sdcProblem", "numeric"), definition=function(object, value) {
object@startJ <- value
validObject(object)
object
})
setReplaceMethod("s_indicesDealtWith", signature=c("sdcProblem"), definition=function(object, value) {
object@indicesDealtWith <- value
validObject(object)
object
})
setMethod("c_rule_freq", signature=c("sdcProblem", "list"), definition=function(object, input) {
pI <- g_problemInstance(object)
if (input$allowZeros == TRUE) {
suppInd <- which(g_freq(pI) <= input$maxN)
} else {
f <- g_freq(pI)
suppInd <- which(f > 0 & f <= input$maxN)
zeroInd <- which(g_freq(pI) == 0 & !g_sdcStatus(pI) %in% c("u", "x"))
if (length(zeroInd) > 0) {
s_sdcStatus(pI) <- list(
index = zeroInd,
vals = rep("z", length(zeroInd))
)
}
}
if (length(suppInd) > 0) {
s_sdcStatus(pI) <- list(
index = suppInd,
vals = rep("u", length(suppInd))
)
}
s_problemInstance(object) <- pI
validObject(object)
return(object)
})
setMethod("c_heuristic_solution", signature=c("sdcProblem", "list"), definition=function(object, input) {
aProb <- input[[1]]
validCuts <- input[[2]]
solver <- input[[3]]$solver
verbose <- input[[3]]$verbose
### create incremental attacker problem
pI <- g_problemInstance(object)
dimInfoObj <- g_dimInfo(object)
primSupps <- g_primSupps(pI)
secondSupps <- g_secondSupps(pI)
forcedCells <- g_forcedCells(pI)
nrVars <- g_nrVars(pI)
weights <- ci <- g_weight(pI)
ci[primSupps] <- 0
ci[secondSupps] <- 0
lb <- g_lb(pI)
ub <- g_ub(pI)
# required later in the cleanup-procedure
LB <- LBdefault <- weights - lb
UB <- UBdefault <- ub - weights
m1 <- create_m_matrix(obj = object, convert = TRUE)
m2 <- m1
m2@v <- -1* m2@v
AInc <- c_bind(object=m1, input=list(m2, bindRow=FALSE))
nrConstraints <- nrow(AInc)
objective <- rep(ci, 2)
direction <- rep("==", g_nr_rows(AInc))
rhs <- rep(0, g_nr_rows(AInc))
types <- rep("C", g_nr_cols(AInc))
boundsLower <- list(ind=1:g_nr_cols(AInc), val=rep(0, g_nr_cols(AInc)))
boundsUpper <- list(ind=1:g_nr_cols(AInc), val=c(UB, LB))
aProbInc <- new("linProb",
objective=objective,
constraints=AInc,
direction=direction,
rhs=rhs,
boundsLower=boundsLower,
boundsUpper=boundsUpper,
types=types)
# make sure that cells that must be published
# are not part of the heuristic solution
if ( length(forcedCells) > 0 ) {
for ( u in 1:length(forcedCells) ) {
con <- rep(0, g_nr_cols(AInc))
con[c(forcedCells[u], nrVars+forcedCells[u])] <- c(1,-1)
aCon <- init.cutList(type='singleCut', input=list(vals=con, dir="==", rhs=0))
s_add_complete_constraint(aProbInc) <- list(aCon)
}
}
x <- rep(0, g_nr_cols(AInc))
UPL <- g_UPL(pI)
LPL <- g_LPL(pI)
SPL <- g_SPL(pI)
SUP <- primSupps
for ( i in seq_along(primSupps) ) {
cellInd <- primSupps[i]
if ( verbose ) {
cat("finding additional cells to protect primSupp",i,"|",length(primSupps),"...\n")
}
con1 <- con2 <- x
con1[cellInd] <- 1
con2[nrVars+cellInd] <- 1
con3 <- con1 - con2 # page 1018: fichetti and salazar!! (- is correct!)
if ( UPL[cellInd] > 0 ) {
# update and solve: y_ik_minus <- 0 and y_ik_plus <- UPL_ik
aCon <- init.cutList(type='multipleCuts', input=list(mat=init.simpleTriplet(type='simpleTriplet', input=list(mat=rbind(con1, con2))), dir=rep("==", 2), rhs=c(UPL[cellInd], 0)))
prob <- aProbInc
s_add_complete_constraint(prob) <- list(aCon)
sol <- c_solve_problem(prob, input=list(solver))$solution
v <- sol[1:nrVars]+sol[(nrVars+1):length(sol)]
v[which(is.zero(v))] <- 0
addIndex <- which ( v > 0 )
if ( length(addIndex) > 0 ) {
SUP <- unique(c(SUP, addIndex))#
ci[SUP] <- 0
s_objective(aProbInc) <- list(rep(ci, 2))
LB <- ci - lb
UB <- ub - ci
}
}
if ( LPL[cellInd] > 0 ) {
# update and solve: y_ik_minus <- LPL_ik and y_ik_plus <- 0
aCon <- init.cutList(type='multipleCuts', input=list(mat=init.simpleTriplet(type='simpleTriplet', input=list(mat=rbind(con1, con2))), dir=rep("==", 2), rhs=c(0, LPL[cellInd])))
prob <- aProbInc
s_add_complete_constraint(prob) <- list(aCon)
sol <- c_solve_problem(prob, input=list(solver))$solution
v <- sol[1:nrVars]+sol[(nrVars+1):length(sol)]
v[which(is.zero(v))] <- 0
addIndex <- which ( v > 0 )
if ( length(addIndex) > 0 ) {
SUP <- unique(c(SUP, addIndex))
ci[SUP] <- 0
s_objective(aProbInc) <- list(rep(ci, 2))
LB <- ci - lb
UB <- ub - ci
}
}
if ( SPL[cellInd] > 0 ) {
# update and solve: y_ik_plus + y_ik_minus <- SPL_ik
aCon <- init.cutList(type='singleCut', input=list(vals=con3, dir="==", rhs=SPL[cellInd]))
prob <- aProbInc
s_add_complete_constraint(prob) <- list(aCon)
sol <- c_solve_problem(prob, input=list(solver))$solution
v <- sol[1:nrVars]+sol[(nrVars+1):length(sol)]
v[which(is.zero(v))] <- 0
addIndex <- which ( v > 0 )
if ( length(addIndex) > 0 ) {
SUP <- unique(c(SUP, addIndex))
ci[SUP] <- 0
s_objective(aProbInc) <- list(rep(ci, 2))
LB <- ci - lb
UB <- ub - ci
}
}
}
if ( verbose ) {
cat(length(SUP) - length(primSupps),"additional cells have been suppressed in the heuristic solution!\n")
}
### cleanup: remove redundant suppressions....
# FIXME: use constraint pool to search for violations in the constraint pool
# aProb has already been calculated and is an input parameter of this method!
nrConstraints <- length(g_objective(aProb)) - 2*length(weights)
addedSupps <- setdiff(SUP, primSupps)
orderAddedSupps <- order(weights[addedSupps], decreasing=TRUE)
xi <- rep(0, length(UPL))
xi[SUP] <- 1 # we need to check xi
counter <- 0
for ( i in orderAddedSupps ) {
counter <- counter + 1
if ( verbose ) {
cat("checking if removing cell",counter,"|",length(addedSupps),"still yields a valid suppression pattern...\n")
}
cellInd <- addedSupps[i]
limits <- c(LPL[cellInd], UPL[cellInd], SPL[cellInd])
xiWorking <- xi
xiWorking[cellInd] <- 0 # we need to check if xi without xi[i] is a valid pattern
UBWorking <- UB
LBWorking <- LB
UBWorking[cellInd] <- UBdefault[cellInd]
LBWorking[cellInd] <- LBdefault[cellInd]
######################
# check if any validCuts are not valid with xiWorking!
# validCuts needs to be supplemented in function call
### get a constraint from validCuts
if ( g_nr_constraints(validCuts) > 0 ) {
conMat <- g_constraints(validCuts)
result <- rep(NA, g_nr_rows(conMat))
for ( z in 1:g_nr_rows(conMat) ) {
expr <- paste(sum(xiWorking[g_col_ind(g_row(conMat, input=list(z)))]), g_direction(validCuts)[z], g_rhs(validCuts)[z])
result[z] <- eval(parse(text=expr))
}
} else {
result <- TRUE
}
if ( any(result==FALSE) ) {
#cat("additionally suppressed cell cannot be removed (violated constraint in the pool found)!\n")
} else {
# no constraint was violated, we have to solve the incremental attacker problems
# we need to solve the attackers problem for each sensitive cell twice
if ( limits[3] != 0 ) {
# solveAttackerProblem (upper bound)
rhs <- rep(0, length(g_rhs(aProb)))
rhs[cellInd] <- 1
s_rhs(aProb) <- list(rhs)
s_objective(aProb) <- list(c(weights + UBWorking*xiWorking, -(weights-xiWorking*LBWorking), rep(0, nrConstraints)))
up <- c_solve_problem(aProb, input=list(solver))
# solveAttackerProblem (lower bound)
s_rhs(aProb) <- list(-1*rhs)
down <- c_solve_problem(aProb, input=list(solver))
calcDown <- -down$optimum
calcUp <- up$optimum
} else {
# solve attackers problem (minimize)
if ( limits[1] != 0 ) {
rhs <- rep(0, length(g_rhs(aProb)))
rhs[cellInd] <- -1
s_rhs(aProb) <- list(rhs)
s_objective(aProb) <- list(c(weights + UBWorking*xiWorking, -(weights-xiWorking*LBWorking), rep(0, nrConstraints)))
down <- c_solve_problem(aProb, input=list(solver))
calcDown <- -down$optimum
}
# solve attackers problem (maximize)
if ( limits[2] != 0 ) {
rhs <- rep(0, length(g_rhs(aProb)))
rhs[cellInd] <- 1
s_rhs(aProb) <- list(rhs)
s_objective(aProb) <- list(c(weights + UBWorking*xiWorking, -(weights-xiWorking*LBWorking), rep(0, nrConstraints)))
up <- c_solve_problem(aProb, input=list(solver))
calcUp <- up$optimum
}
}
# check for feasibility
valid <- TRUE
if ( limits[3] > 0 & calcUp - calcDown < SPL[i] ) {
valid <- FALSE
} else {
if ( limits[1] > 0 & calcDown > weights[i] - LPL[i] ) {
valid <- FALSE
}
if ( limits[2] > 0 & calcUp < weights[i] + UPL[i] ) {
valid <- FALSE
}
}
if ( valid ) {
xi[cellInd] <- 0
SUP <- setdiff(SUP, cellInd)
if ( verbose ) {
cat("redundant suppression found! --> removing cell!\n")
}
}
# else: additionally suppressed cell cannot be removed!
}
}
return(xi)
})
setMethod("c_anon_worker", signature=c("sdcProblem", "list"), definition=function(object, input) {
timeLimit <- input$timeLimit
verbose <- input$verbose
save <- input$save
if (save == TRUE) {
files <- NULL
}
pI <- g_problemInstance(object)
sdcStatusBegin <- g_sdcStatus(pI)
primSupps <- primSuppsOrig <- g_primSupps(pI)
indexPool <- numeric()
allStrIDs <- g_strID(pI)
if (input$method == "OPT") {
if (input$useC == TRUE) {
result <- csp_cpp(
sdcProblem = object,
attackonly = FALSE,
verbose = input$verbose
)
} else {
result <- c_cut_and_branch(object, input)
}
if (save == TRUE) {
fn <- paste0(input$method, "-object-final.rds")
saveRDS(object, file = fn)
}
return(result)
}
# HITAS or HYPERCUBE
# check where we should start (saved file)
partition <- g_partition(object)
startI <- g_startI(object)
startJ <- g_startJ(object)
if (startI != 1 | startJ != 1) {
maxI <- partition$nrGroups
if (startJ < length(partition$indices[[startI]])) {
startJ <- startJ + 1
} else {
startJ <- 1
startI <- startI + 1
}
}
if (input$method == "HITAS") {
for (i in startI:(partition$nrGroups)) {
s_startJ(object) <- 1 # reset j before updating i
s_startI(object) <- i
#indexPool <- g_indicesDealtWith(object)
if (i == 1) {
indexPool <- c()
} else {
indexPool <- sort(unique(unlist(partition$indices[1:(i - 1)])))
}
ind <- partition$indices[[i]]
beginJ <- ifelse(i==startI, startJ, 1)
for (j in beginJ:(length(ind))) {
s_startJ(object) <- j
currentIndices <- ind[[j]] # within complete table
### cells with status 'u' or 'x' exist
pI <- g_problemInstance(object)
if ( any(g_sdcStatus(pI)[currentIndices] %in% c("u","x")) & length(currentIndices) > 1 ) {
if ( verbose ) {
cat("Starting to solve problem",j,"/",length(ind),"in group",i,"/",partition$nrGroups,"!\n")
}
### if we have cells with "u" or "x" we need to protect
### the corresponding subtable
### reduce problemInstance
probNew <- c_reduce_problem(object, input=list(currentIndices))
pI.new <- g_problemInstance(probNew)
### is it necessary to protect the table??
currentPrimSupps <- primSupps[!is.na(match(primSupps, currentIndices ))]
### indices that have already been inner cells in
### tables dealt earlier
# FIXME: save indexpool somehow
indicesDealtWith <- which(currentIndices %in% indexPool) #in current current subproblem
### fix marginal-cells
### --> its-suppression state must not change!
currentPattern <- g_sdcStatus(g_problemInstance(probNew))
introducedSupps <- indicesDealtWith[which(currentPattern[indicesDealtWith] == "x")]
if ( length(introducedSupps) > 0 ) {
### secondary suppressions from upper tables
s_sdcStatus(pI.new) <- list(index=introducedSupps,vals=rep("u", length(introducedSupps)))
### temporarily change LPL, UPL, SPL for these cells
LPL.current <- g_LPL(pI.new)[introducedSupps]
UPL.current <- g_UPL(pI.new)[introducedSupps]
SPL.current <- g_SPL(pI.new)[introducedSupps]
s_LPL(pI.new) <- list(index=introducedSupps, vals=rep(0, length(introducedSupps)))
s_UPL(pI.new) <- list(index=introducedSupps, vals=rep(0, length(introducedSupps)))
s_SPL(pI.new) <- list(index=introducedSupps, vals=rep(0.1, length(introducedSupps)))
}
### force non-suppression of cells that have already been dealt with
indForced <- indicesDealtWith[which(currentPattern[indicesDealtWith] == "s")]
if ( length(indForced) > 0 ) {
s_sdcStatus(pI.new) <- list(index=indForced,vals=rep("z", length(indForced)))
}
s_problemInstance(probNew) <- pI.new
### solving the problem
if (input$useC == TRUE) {
probNew <- csp_cpp(
sdcProblem = probNew,
attackonly = FALSE,
verbose = input$verbose
)
} else {
probNew <- c_cut_and_branch(object = probNew, input = input)
}
### update sdcStatus
status <- g_sdcStatus(g_problemInstance(probNew))
pI <- g_problemInstance(object)
if ( length(indForced) > 0 ) {
status[indForced] <- "s"
}
if ( length(introducedSupps) > 0 ) {
status[introducedSupps] <- "x"
s_LPL(pI) <- list(index=currentIndices[introducedSupps], vals=LPL.current)
s_UPL(pI) <- list(index=currentIndices[introducedSupps], vals=UPL.current)
s_SPL(pI) <- list(index=currentIndices[introducedSupps], vals=SPL.current)
}
s_sdcStatus(pI) <- list(index=currentIndices, vals=status)
s_problemInstance(object) <- pI
}
if (save == TRUE) {
if (verbose) {
cat("saving object after i=", i, "and j=", j, "\n")
}
fn <- paste0(input$method, "-object_", i, "-", j, ".rds")
files <- c(files, fn)
save(object, file = fn)
# removing old files
if (length(files) > 1) {
sapply(rev(files)[-1], file.remove)
files <- files[length(files)]
}
}
}
### update indices that we have already dealt with
s_indicesDealtWith(object) <- unique(c(indexPool, currentIndices))
}
}
if (input$method == 'HYPERCUBE') {
runInd <- TRUE
nrRuns <- 1
while ( runInd == TRUE ) {
if (input$verbose) {
cat("The algorithm is now starting run",nrRuns,"\n")
}
tmpSupps <- c(g_primSupps(g_problemInstance(object)), g_secondSupps(g_problemInstance(object)))
forcedCells <- g_forcedCells(g_problemInstance(object))
for ( i in startI:(partition$nrGroups) ) {
s_startJ(object) <- 1 # reset j before updating i
s_startI(object) <- i
ind <- partition$indices[[i]]
beginJ <- ifelse(i==startI, startJ, 1)
for ( j in beginJ:(length(ind)) ) {
s_startJ(object) <- j
currentIndices <- ind[[j]] # within complete table
### cells with status 'u' or 'x' exist
pI <- g_problemInstance(object)
# when using HYPERCUBE: we only check primary suppressions because we
# temporarily set secondary suppressions to "u"
if ( any(g_sdcStatus(pI)[currentIndices] == "u") & length(currentIndices) > 1 ) {
if ( verbose ) {
cat("Starting to solve problem",j,"/",length(ind),"in group",j,"/",partition$nrGroups,"!\n")
}
### if we have cells with "u", we need to protect
### the corresponding subtable
### reduce problemInstance
probNew <- c_reduce_problem(object, input=list(currentIndices))
pI.new <- g_problemInstance(probNew)
### is it necessary to protect the table??
currentPrimSupps <- primSupps[!is.na(match(primSupps, currentIndices ))]
s_problemInstance(probNew) <- pI.new
### solving the problem
probNew <- c_ghmiter(object=probNew, input=input)
### update sdcStatus
status <- g_sdcStatus(g_problemInstance(probNew))
pI <- g_problemInstance(object)
s_sdcStatus(pI) <- list(index=currentIndices, vals=status)
s_problemInstance(object) <- pI
}
if ( save == TRUE ) {
if ( verbose ) {
cat("saving object after i=", i, "and j=", j, "\n")
}
fn <- paste0(input$method, "-object_", i, "-", j, ".rds")
files <- c(files, fn)
save(object, file = fn)
# removing old files
if (length(files) > 1) {
sapply(rev(files)[-1], file.remove)
files <- files[length(files)]
}
}
}
}
### protect secondary suppressions ###
pI <- g_problemInstance(object)
allSupps <- c(g_primSupps(pI), g_secondSupps(pI))
newSupps <- setdiff(allSupps, tmpSupps)
pI <- g_problemInstance(object)
nrVars <- length(g_freq(pI))
if (length(newSupps) == 0) {
runInd <- FALSE
newSdcStatus <- rep('s', length=nrVars)
newSdcStatus[forcedCells] <- 'z'
newSdcStatus[tmpSupps] <- 'x'
newSdcStatus[primSuppsOrig] <- 'u'
s_sdcStatus(pI) <- list(index=1:nrVars, vals=newSdcStatus)
s_problemInstance(object) <- pI
} else {
newSdcStatus <- rep('s', length=nrVars)
newSdcStatus[forcedCells] <- 'z'
newSdcStatus[tmpSupps] <- 'x'
newSdcStatus[newSupps] <- 'u'
s_sdcStatus(pI) <- list(index=1:nrVars, vals=newSdcStatus)
s_problemInstance(object) <- pI
nrRuns <- nrRuns + 1
}
} # while loop
}
return(object)
})
setMethod("c_opt_cpp", signature=c("sdcProblem", "list"), definition=function(object, input) {
timeLimit <- input$timeLimit
verbose <- input$verbose
save <- input$save
pI <- g_problemInstance(object)
sdcStatusBegin <- g_sdcStatus(pI)
primSupps <- primSuppsOrig <- g_primSupps(pI)
indexPool <- numeric()
allStrIDs <- g_strID(pI)
invisible(csp_cpp(sdcProblem=object, attackonly=FALSE, verbose=input$verbose))
})
setMethod("c_hitas_cpp", signature=c("sdcProblem", "list"), definition=function(object, input) {
timeLimit <- input$timeLimit
verbose <- input$verbose
save <- input$save
pI <- g_problemInstance(object)
sdcStatusBegin <- g_sdcStatus(pI)
primSupps <- primSuppsOrig <- g_primSupps(pI)
indexPool <- numeric()
allStrIDs <- g_strID(pI)
partition <- g_partition(object)
# save protection levels
LPL.start <- g_LPL(pI)
UPL.start <- g_UPL(pI)
SPL.start <- g_SPL(pI)
run_ind <- TRUE
while ( run_ind ) {
for ( i in 1:(partition$nrGroups) ) {
s_startJ(object) <- 1 # reset j before updating i
s_startI(object) <- i
indexPool <- NULL
if ( i > 1 ) {
indexPool <- sort(unique(unlist(partition$indices[1:(i-1)])))
}
ind <- partition$indices[[i]]
for ( j in 1:(length(ind)) ) {
is_ok <- TRUE
s_startJ(object) <- j
currentIndices <- ind[[j]] # within complete table
# cells with status "u" or "x" exist
pI <- g_problemInstance(object)
if ( any(g_sdcStatus(pI)[currentIndices] %in% c("u","x")) & length(currentIndices) > 1 ) {
if ( verbose ) {
cat("Starting to solve problem",j,"/",length(ind),"in group",i,"/",partition$nrGroups,"!\n")
}
# if we have cells with "u" or "x" we need to protect
# the corresponding subtable --> reduce problemInstance
probNew <- c_reduce_problem(object, input=list(currentIndices))
pI.new <- g_problemInstance(probNew)
# is it necessary to protect the table??
currentPrimSupps <- primSupps[!is.na(match(primSupps, currentIndices))]
# indices that have already been inner cells in tables dealt earlier
indicesDealtWith <- which(currentIndices %in% indexPool) # in current current subproblem
# we have to fix marginal-cells: --> their suppression status must not change!
currentPattern <- g_sdcStatus(g_problemInstance(probNew))
introducedSupps <- indicesDealtWith[which(currentPattern[indicesDealtWith] == "x")]
if ( length(introducedSupps) > 0 ) {
# secondary suppressions from upper tables
s_sdcStatus(pI.new) <- list(index=introducedSupps, vals=rep("u", length(introducedSupps)))
# temporarily change LPL, UPL, SPL for these cells
LPL.current <- g_LPL(pI.new)[introducedSupps]
UPL.current <- g_UPL(pI.new)[introducedSupps]
SPL.current <- g_SPL(pI.new)[introducedSupps]
s_LPL(pI.new) <- list(index=introducedSupps, vals=rep(0, length(introducedSupps)))
s_UPL(pI.new) <- list(index=introducedSupps, vals=rep(0, length(introducedSupps)))
s_SPL(pI.new) <- list(index=introducedSupps, vals=rep(0.1, length(introducedSupps)))
}
# force non-suppression of cells that have already been dealt with
indForced <- indicesDealtWith[which(currentPattern[indicesDealtWith] == "s")]
if ( length(indForced) > 0 ) {
s_sdcStatus(pI.new) <- list(index=indForced, vals=rep("z", length(indForced)))
}
s_problemInstance(probNew) <- pI.new
# solve the problem using c++ implementation
res <- csp_cpp(sdcProblem=probNew, attackonly=FALSE, verbose=input$verbose)
if ( is.null(res) ) {
cat("\nWe got a problem and need to relax some conditions!\n\n")
old.status <- probNew@problemInstance@sdcStatus
ii <- which(old.status %in% c("z") & probNew@problemInstance@Freq > 0)
if ( length(ii) == 0 ) {
stop("This is a really nasty problem. No solution can be computed. Please contact the package maintainer.\n")
}
probNew@problemInstance@sdcStatus[ii] <- "s"
res <- csp_cpp(sdcProblem=probNew, attackonly=FALSE, verbose=input$verbose)
if ( is.null(res) ) {
stop("This is a really nasty problem. No solution can be computed. Please contact the package maintainer.\n")
}
probNew <- res
new.status <- probNew@problemInstance@sdcStatus
xx <- data.frame(currentIndices=currentIndices,old=old.status, new=new.status, freq=probNew@problemInstance@Freq)
ii <- which(new.status=="x" & old.status=="z")
updated_status <- rep("s", length(old.status))
updated_status[which(old.status=="u")] <- "u"
updated_status[probNew@problemInstance@Freq==0] <- "z"
updated_status[ii] <- "u"# previously "z", now "u"
xx <- sdcStatusBegin
xx[currentIndices] <- updated_status
pI <- g_problemInstance(object)
s_LPL(pI) <- list(index=currentIndices[ii], vals=rep(0, length(ii)))
s_UPL(pI) <- list(index=currentIndices[ii], vals=rep(0, length(ii)))
s_SPL(pI) <- list(index=currentIndices[ii], vals=rep(0.1, length(ii)))
s_sdcStatus(pI) <- list(index=1:length(xx), vals=xx)
s_problemInstance(object) <- pI
is_ok <- FALSE
} else {
probNew <- res
}
# break j-loop
if ( !is_ok ) {
break
}
# update sdcStatus
status <- g_sdcStatus(g_problemInstance(probNew))
pI <- g_problemInstance(object)
if ( length(indForced) > 0 ) {
status[indForced] <- "s"
}
if ( length(introducedSupps) > 0 ) {
status[introducedSupps] <- "x"
s_LPL(pI) <- list(index=currentIndices[introducedSupps], vals=LPL.current)
s_UPL(pI) <- list(index=currentIndices[introducedSupps], vals=UPL.current)
s_SPL(pI) <- list(index=currentIndices[introducedSupps], vals=SPL.current)
}
s_sdcStatus(pI) <- list(index=currentIndices, vals=status)
s_problemInstance(object) <- pI
}
}
# break i-loop
if ( !is_ok ) {
break
}
# update indices that we have already dealt with
s_indicesDealtWith(object) <- unique(c(indexPool, currentIndices))
}
if ( is_ok ) {
run_ind <- FALSE
}
}
pI <- g_problemInstance(object)
s_LPL(pI) <- list(index=1:g_nrVars(pI), vals=LPL.start)
s_UPL(pI) <- list(index=1:g_nrVars(pI), vals=UPL.start)
s_SPL(pI) <- list(index=1:g_nrVars(pI), vals=SPL.start)
sdcStatus <- g_sdcStatus(pI)
ii <- which(sdcStatus %in% c("u", "x"))
sdcStatus[ii] <- "x"
sdcStatus[primSuppsOrig] <- "u"
s_sdcStatus(pI) <- list(index=1:g_nrVars(pI), vals=sdcStatus)
s_problemInstance(object) <- pI
invisible(object)
})
setMethod("c_cut_and_branch", signature=c("sdcProblem", "list"), definition=function(object, input) {
timeLimit <- input$timeLimit
fixVariables <- input$fixVariables
maxVars <- input$maxVars
fastSolution <- input$fastSolution
approxPerc <- input$approxPerc
verbose <- input$verbose
solver <- input$solver
problemInstance <- g_problemInstance(object)
dimInfo <- g_dimInfo(object)
nrVars <- g_nrVars(problemInstance)
freqs <- g_freq(problemInstance)
primSupps <- g_primSupps(problemInstance)
publishVars <- which(g_sdcStatus(problemInstance) == "z")
noBranchVars <- unique(c(primSupps, publishVars))
# Nothing to protect here
if (!g_hasPrimSupps(problemInstance)) {
return(object)
}
# returning heuristic solution
# only if problem size is too large
if (is.null(maxVars)) {
maxVars <- nrVars + 1
}
if (fastSolution) {
maxVars <- 0
}
approx <- ifelse(is.null(approxPerc), FALSE, TRUE)
if (nrVars >= maxVars) {
res <- c_make_att_prob(input=list(objectA=object))
aProb <- res$aProb
validCuts <- res$newCutsMaster
heuristicSolution <- c_heuristic_solution(object, input = list(aProb, validCuts, input))
secondSupps <- setdiff(which(heuristicSolution == 1), primSupps)
if (verbose) {
cat(
"Result: we are returning a possibly non-optimal solution with",
length(secondSupps),
"secondary suppressions because of parameter 'fastSolution' or 'maxVars'!\n"
)
}
if (length(secondSupps) > 0) {
s_sdcStatus(problemInstance) <- list(index = secondSupps, vals = rep("x", length(secondSupps)))
}
out <- new("sdcProblem",
dataObj = g_dataObj(object),
dimInfo = dimInfo,
problemInstance = problemInstance,
partition = g_partition(object),
startI = g_startI(object),
startJ = g_startJ(object),
indicesDealtWith = g_indicesDealtWith(object)
)
return(out)
}
if (verbose) {
cat("running pre-process procedure...\n")
}
resultPreProcess <- c_preprocess(object, input = input)
object <- resultPreProcess$sdcProblem
validCuts <- resultPreProcess$validCuts
aProb <- resultPreProcess$aProb
# no valid cuts have been generated in preprocessing!
if (g_nr_rows(g_constraints(validCuts)) == 0) {
return(object)
}
if (verbose) {
cat("calculating a heuristic solution...\n")
}
heuristicSolution <- c_heuristic_solution(object, input = list(aProb, validCuts, input))
### all solutions found and current best solution
solutions <- list()
bestSolution <- heuristicSolution
solutions[[1]] <- heuristicSolution
startTime <- Sys.time()
timeStop <- FALSE
### cuts due to hierarchical structure
if (verbose) {
cat("calculating structural cuts...\n")
}
structureCuts <- c_gen_structcuts(object, input = list())
# does heuristicSolution violates any cuts from structure-cuts??
#c_check_violation(structureCuts, input=list(heuristicSolution, g_weight(problemInstance)))
validCuts <- c_bind_together(validCuts, input = list(structureCuts))
#######
### create master problem and add constraints derived in pre-processing
mProb <- c_make_masterproblem(problemInstance, input = list())
s_add_complete_constraint(mProb) <- list(validCuts)
if (verbose) {
cat("solving the original master problem (no additional constraints)...\n")
}
masterSolution <- c_solve_problem(mProb, input = list(solver))
masterObj <- masterSolution$optimum
xi <- masterSolution$solution
xi[is.zero(xi)] <- 0
xi[is.one(xi)] <- 1
### initialize bounds
currentBestBoundDown <- masterObj
currentBestBoundUp <- sum(g_objective(mProb) * heuristicSolution)
branchedVars <- NULL
### check if we have already the optimum solution (without rounding errors)
runInd <- TRUE
if (abs(masterObj - currentBestBoundUp) < 0.1) {
runInd <- FALSE
} else {
### fixing variables
if (fixVariables == TRUE & currentBestBoundUp >= currentBestBoundDown) {
if (verbose) {
cat("fixing variables...\n")
}
fixedVars <- c_fix_variables(mProb, input=list(currentBestBoundDown, currentBestBoundUp, primSupps))
if (length(fixedVars) > 0) {
if (verbose) {
cat("--> setting", length(fixedVars), "variables to 0!\n")
}
bounds <- g_bounds(mProb)
bounds$upper$val[fixedVars] <- 0
s_bounds(mProb) <- bounds
}
}
### constraint pool initialization
problemPool <- list()
problemPool[[1]] <- init.cutList(type = 'empty', input = list(nrCols = nrVars))
### solving
selectFirst <- TRUE
LPL <- g_LPL(problemInstance)
UPL <- g_UPL(problemInstance)
SPL <- g_SPL(problemInstance)
weights <- g_weight(problemInstance)
LB <- weights - g_lb(problemInstance)
UB <- g_ub(problemInstance) - weights
nrConstraints <- length(g_objective(aProb)) - 2 * length(weights)
### initialize constants (probably function-parameters later)
selectFirst <- FALSE
### TODO: stop procedure after given time or nr or solutions..
iter <- 0
}
while (runInd) {
iter <- iter + 1
selectInd <- ifelse(selectFirst == TRUE, 1, length(problemPool))
newCuts <- init.cutList(type = 'empty', input = list(nrCols = nrVars))
AttProbDown <- AttProbUp <- rep(NA, length(primSupps))
status <- NULL
for (i in 1:length(primSupps)) {
cellInd <- primSupps[i]
limits <- c(LPL[cellInd], UPL[cellInd], SPL[cellInd])
# we need to solve the attackers problem for each sensitive cell twice
if ( limits[3] != 0 ) {
# solveAttackerProblem (upper bound)
rhs <- rep(0, length(g_rhs(aProb)))
rhs[cellInd] <- 1
s_rhs(aProb) <- list(rhs)
s_objective(aProb) <- list(c(weights + UB*xi, -(weights-xi*LB), rep(0, nrConstraints)))
up <- c_solve_problem(aProb, input=list(solver))
### solveAttackerProblem (lower bound)
s_rhs(aProb) <- list(-1*rhs)
down <- c_solve_problem(aProb, input=list(solver))
AttProbDown[i] <- -down$optimum
AttProbUp[i] <- up$optimum
status <- c(status, down$status, up$status)
#cat('limits ( origValue=',weights[cellInd],') : [',AttProbDown[i],':',AttProbUp[i],']\n')
alpha.down <- down$solution[1:nrVars]
alpha.up <- up$solution[1:nrVars]
beta.down <- down$solution[(nrVars+1):(2*nrVars)]
beta.up <- up$solution[(nrVars+1):(2*nrVars)]
} else {
# solve attackers problem (minimize)
if ( limits[1] != 0 ) {
rhs <- rep(0, length(g_rhs(aProb)))
rhs[cellInd] <- -1
s_rhs(aProb) <- list(rhs)
down <- c_solve_problem(aProb, input=list(solver))
AttProbDown[i] <- -down$optimum
}
# solve attackers problem (maximize)
if ( limits[2] != 0 ) {
rhs <- rep(0, length(g_rhs(aProb)))
rhs[cellInd] <- 1
s_rhs(aProb) <- list(rhs)
s_objective(aProb) <- list(c(weights + UB*xi, -(weights-xi*LB), rep(0, nrConstraints)))
up <- c_solve_problem(aProb, input=list(solver))
AttProbUp[i] <- up$optimum
}
}
# SPL
if ( limits[3] != 0 & AttProbUp[i] - AttProbDown[i] < limits[3] ) {
status <- c(status, down$status, up$status)
alpha.down <- down$solution[1:nrVars]
alpha.up <- up$solution[1:nrVars]
beta.down <- down$solution[(nrVars+1):(2*nrVars)]
beta.up <- up$solution[(nrVars+1):(2*nrVars)]
v <- (alpha.down+alpha.up)*UB + (beta.down+beta.up)*LB
v[which(is.zero(v))] <- 0
if ( any(v != 0) )
s_add_complete_constraint(newCuts) <- list(init.cutList(type='singleCut', input=list(vals=v, dir=">=", rhs=limits[3])))
} else {
if ( limits[1] != 0 & freqs[primSupps[i]] - AttProbDown[i] < limits[1] ) { # LPL
status <- c(status, down$status)
alpha.down <- down$solution[1:nrVars]
beta.down <- down$solution[(nrVars+1):(2*nrVars)]
v <- alpha.down*UB + beta.down*LB
v[which(is.zero(v))] <- 0
if ( any(v != 0) )
s_add_complete_constraint(newCuts) <- list(init.cutList(type='singleCut', input=list(vals=v, dir=">=", rhs=limits[1])))
}
if ( limits[2] != 0 & AttProbUp[i] - freqs[primSupps[i]] < limits[2] ) { # UPL
status <- c(status, up$status)
alpha.up <- up$solution[1:nrVars]
beta.up <- up$solution[(nrVars+1):(2*nrVars)]
v <- alpha.up*UB + beta.up*LB
v[which(is.zero(v))] <- 0
if ( any(v != 0) )
s_add_complete_constraint(newCuts) <- list(init.cutList(type='singleCut', input=list(vals=v, dir=">=", rhs=limits[2])))
}
}
#cat('limits ( origValue=',weights[cellInd],') : [',AttProbDown[i],':',AttProbUp[i],']\n')
}
if ( g_nr_constraints(newCuts) > 0 ) {
# strengthen cuts
if ( verbose ) {
cat("strengthening the cuts and adding",g_nr_constraints(newCuts),"new derived cuts to master problem...\n")
}
newCuts <- c_strengthen(newCuts)
s_add_complete_constraint(mProb) <- list(newCuts)
}
### check for duplicated constraints
indRem <- which(duplicated(cbind(as.matrix(g_constraints(mProb)), g_direction(mProb), g_rhs(mProb))))
if ( length(indRem) > 0 ) {
#if ( verbose ) {
# cat("removing",length(indRem),"duplicated constraints...\n")
#}
s_remove_complete_constraint(mProb) <- list(indRem)
}
### bridgeless inequalities only at root-node ####
bridgelessCandidates <- setdiff(which(xi == 1), primSupps)
if ( iter == 1 & length(bridgelessCandidates) > 0 ) {
brCuts <- init.cutList(type='empty', input=list(nrCols=nrVars))
if ( verbose ) {
cat("adding",length(bridgelessCandidates),"bridgeless ineqalities!\n")
}
for ( z in seq_along(bridgelessCandidates) ) {
bridgelessInd <- bridgelessCandidates[z]
### solveAttackerProblem (upper bound)
rhs <- rep(0, length(g_rhs(aProb)))
rhs[bridgelessInd] <- 1
s_rhs(aProb) <- list(rhs)
s_objective(aProb) <- list(c(weights + UB*xi, -(weights-xi*LB), rep(0, nrConstraints)))
up <- c_solve_problem(aProb, input=list(solver))
### solveAttackerProblem (lower bound)
s_rhs(aProb) <- list(-1*rhs)
down <- c_solve_problem(aProb, input=list(solver))
alpha.down <- down$solution[1:nrVars]
alpha.up <- up$solution[1:nrVars]
beta.down <- down$solution[(nrVars+1):(2*nrVars)]
beta.up <- up$solution[(nrVars+1):(2*nrVars)]
brIneq <- (alpha.down+alpha.up)*UB + (beta.down+beta.up)*LB
brIneq[is.zero(brIneq)] <- 0
brIneq[brIneq > 0] <- 1
brIneq[bridgelessInd] <- -1
s_add_complete_constraint(brCuts) <- list(init.cutList(type='singleCut', input=list(vals=brIneq, dir=">=", rhs=0)))
}
if ( g_nr_constraints(brCuts) > 0 ) {
s_add_complete_constraint(mProb) <- list(brCuts)
}
}
mProbWorking <- mProb
# eventually update the lower bound...
tmpSolution <- c_solve_problem(mProbWorking, input = list(solver))
tmpObj <- tmpSolution$optimum
if (tmpObj > currentBestBoundDown & tmpObj <= currentBestBoundUp) {
currentBestBoundDown <- tmpObj
}
if (abs(currentBestBoundUp - currentBestBoundDown) < 1) {
# optimal solution found!
break
}
if (g_nr_constraints(problemPool[[selectInd]]) > 0) {
if (verbose) {
cat("adding", g_nr_constraints(problemPool[[selectInd]]), "constraints to the master problem...\n")
}
mProbWorking <- mProb
s_add_complete_constraint(mProbWorking) <- list(problemPool[[selectInd]])
}
if ( verbose ) {
cat("solving the master problem with", length(g_rhs(mProbWorking)), "constraints...\n")
}
masterSolution <- c_solve_problem(mProbWorking, input=list(solver))
masterObj <- masterSolution$optimum
xi <- masterSolution$solution
xi[is.zero(xi)] <- 0
xi[is.one(xi)] <- 1
if (verbose) {
cat("best-bounds: [",currentBestBoundDown,":",currentBestBoundUp,"] and objVal =",masterObj,"with sum(xi)=",sum(xi),"\n")
}
#cat("current boundUp =",currentBestBoundUp,"and objVal =",masterObj,"with sum(xi)=",sum(xi),"\n")
### again fixing variables
#if ( fixVariables == TRUE ) {
# newFixedVars <- c_fix_variables(mProb, input=list(currentBestBoundDown, currentBestBoundUp, primSupps))
# if ( !all(newFixedVars) %in% fixedVars ) {
# cat("setting",length(newFixedVars),"variables to 0!\n")
# bounds <- g_bounds(mProb)
# bounds$upper$val[newFixedVars] <- 0
# s_bounds(mProb) <- bounds
# }
#}
### checking if we can prune the current node
prune <- FALSE
pruneReason <- NULL
# a) valid (protected) integer solution
if (all(is.wholenumber(xi)) && c_is_protected_solution(problemInstance, input=list(input1=AttProbDown, input2=AttProbUp))) {
prune <- TRUE
pruneReason <- c(pruneReason, "V") # valid
}
# b) infeasibility
if (sum(status) != 0) {
prune <- TRUE
pruneReason <- c(pruneReason, "I") # infeasible
}
# c) bounds
if (approx == TRUE) {
if (currentBestBoundUp - masterObj <= currentBestBoundUp * (approxPerc / 100)) {
prune <- TRUE
pruneReason <- c(pruneReason, "B") # bounds
}
if (masterObj - currentBestBoundDown < 0) {
prune <- TRUE
pruneReason <- c(pruneReason, "B") # bounds
}
} else {
if (abs(masterObj - currentBestBoundUp) <= 0.01) {
prune <- TRUE
pruneReason <- c(pruneReason, "B") # bounds
}
if (masterObj - currentBestBoundDown < 0) {
prune <- TRUE
pruneReason <- c(pruneReason, "B") # bounds
}
}
if (prune == TRUE) {
pruneReason <- unique(pruneReason) # remove eventually 2-'Bs'
if (length(pruneReason) == 2) {
if (pruneReason[1] == "V" & pruneReason[2] == "B") {
#cat("found worse-than optimal integer-solution -> pruning by bounds!\n")
if (masterObj < currentBestBoundUp) {
pruneReason <- "V"
} else {
pruneReason <- "B"
}
}
}
if (length(pruneReason) > 1) {
stop("Error: only one pruning reason possible!", call. = FALSE)
}
if (pruneReason == "V") {
solutions[[length(solutions) + 1]] <- as.integer(xi)
if (masterObj < currentBestBoundUp) {
if (verbose) {
cat("new best integer solution (objval=", masterObj, ") found!:\n")
}
currentBestBoundUp <- masterObj
bestSolution <- as.integer(xi)
}
}
#if (pruneReason == "I") {
# cat("pruning because of infeasibility!\n")
#}
#if (pruneReason == "B") {
# cat("pruning because of known bounds!\n")
#}
problemPool[[selectInd]] <- NULL
if (verbose) {
cat("pruning the current node: reason=",pruneReason,"!. Still",length(problemPool),"nodes in the pool!\n")
}
} else {
## 2) Branching: we extend the problemPool and remove the current node afterwards
branchedVars <- g_col_ind(g_constraints(problemPool[[selectInd]]))
branchVar <- getBranchingVariable(xi, branchedVars, noBranchVars)
if (length(branchVar) == 1) {
cl <- problemPool[[selectInd]]
v <- rep(0, nrVars)
v[branchVar] <- 1
c1 <- c2 <- cl
s_add_complete_constraint(c1) <- list(
init.cutList(
type = 'singleCut',
input = list(
vals = v, dir = "==", rhs = 0
)
)
)
s_add_complete_constraint(c2) <- list(
init.cutList(
type = 'singleCut',
input = list(
vals = v, dir = "==", rhs = 1
)
)
)
problemPool[[length(problemPool) + 1]] <- c1
problemPool[[length(problemPool) + 1]] <- c2
rm(cl)
# now we can prune the current node
problemPool[[selectInd]] <- NULL
rm(c1,c2)
if (verbose) {
cat("branching was required. Problem pool has now", length(problemPool), "nodes!\n")
}
} else {
if (verbose) {
cat("no further branching possible! all branching variables tried!\n")
}
problemPool[[selectInd]] <- NULL
}
}
timeSpent <- as.numeric(floor(difftime(Sys.time(), startTime, units = "mins")))
#cat("timeSpent:"); print(timeSpent)
if (length(problemPool) == 0) {
runInd <- FALSE
} else {
if (!is.null(timeLimit) && timeSpent > timeLimit && length(solutions) > 0) {
runInd <- FALSE
timeStop <- TRUE
}
if (!is.null(timeLimit) && timeSpent > timeLimit && length(solutions) == 0) {
if (verbose) {
cat("Result: the time-limit was reached and no (heuristic) solution could be generated!\n")
}
return(object)
}
}
}
secondSupps <- setdiff(which(bestSolution == 1), primSupps)
objVarHeuristic <- sum(g_objective(mProb) * heuristicSolution)
if (timeStop == FALSE) {
if (currentBestBoundUp == objVarHeuristic) {
if (verbose) {
cat('Result: the heuristic solution was already optimal and has', length(secondSupps), 'secondary suppressions!\n')
}
} else {
improvement <- 100 - (100 / objVarHeuristic) * currentBestBoundUp
if (verbose) {
cat('Result: the heuristic solution was improved by', format(improvement, digits = 2, nsmall = 2), '% and has', length(secondSupps), 'secondary suppressions!!\n '
)
}
}
} else {
if (verbose) {
cat(
"Result: we are returning a possibly non-optimal solution with",
length(secondSupps),
"secondary suppressions because of argument 'timeLimit'!\n"
)
}
}
if ( length(secondSupps) > 0 ) {
s_sdcStatus(problemInstance) <- list(
index = secondSupps,
vals = rep("x", length(secondSupps))
)
}
out <- new("sdcProblem",
dataObj = g_dataObj(object),
dimInfo = dimInfo,
problemInstance = problemInstance,
partition = g_partition(object),
startI = g_startI(object),
startJ = g_startJ(object),
indicesDealtWith = g_indicesDealtWith(object)
)
return(out)
})
setMethod("c_ghmiter", signature=c("sdcProblem", "list"), definition=function(object, input) {
protectionLevel <- input$protectionLevel
suppMethod <- input$suppMethod
suppAdditionalQuader <- input$suppAdditionalQuader
verbose <- input$verbose
pI <- g_problemInstance(object)
strIDs <- g_strID(pI)
strInfo <- g_str_info(g_dimInfo(object))
sdcStatus <- g_sdcStatus(pI)
cellsToProtect <- g_primSupps(pI)
freqs <- g_freq(pI)
# calc infomation on inner|marginal cells
cellInfo <- g_innerAndMarginalCellInfo(object)
# replaces f.recodeIndexVars
indexList <- lapply(1:length(strInfo), function(x) { mySplit(strIDs, strInfo[[x]][1]:strInfo[[x]][2]) } )
for ( i in 1:length(cellsToProtect) ) {
if ( verbose ) {
cat("--> Cell",i,"|",length(cellsToProtect)," (ID:",strIDs[cellsToProtect[i]],")...")
}
diagObj <- c_ghmiter_diag_obj(object, input=list(cellsToProtect[i], indexList, FALSE))
# calculate required information using diagObj
infoObj <- c_ghmiter_calc_info(object, input=list(diagObj, indexList, protectionLevel, FALSE))
if ( !is.null(infoObj) & length(infoObj) == 0 ) {
diagObj <- c_ghmiter_diag_obj(object, input=list(cellsToProtect[i], indexList, TRUE))
infoObj <- c_ghmiter_calc_info(object, list(diagObj, indexList, protectionLevel, TRUE))
if ( !is.null(infoObj) & length(infoObj) == 0 ) {
stop("ghmiter::: error - could not find sensible cube!\n")
}
warning("Cell with Freq=0 has been selected as partner in suppression pattern!\n")
}
# cellToProtect used from diagObj$cellToProtect
suppObj <- c_ghmiter_select_quader(object, input=list(infoObj, input))
if ( !is.null(suppObj) ) {
object <- c_ghmiter_suppress_quader(object, input=suppObj)
# additional quader needs to be found
# only if it is not a single value in the margins
# and the cube includes cells with frequency=1
if ( suppAdditionalQuader==TRUE & suppObj$indikatorSingleItems==TRUE & !(cellsToProtect[i] %in% cellInfo$indexTotCells) ) {
# find additional cube that does not contain the single cells
object <- c_ghmiter_supp_additional(object, input=list(diagObj, infoObj, suppObj, input))
}
}
if ( verbose ) {
cat("[done]\n")
}
}
return(object)
})
setMethod("c_preprocess", signature=c("sdcProblem", "list"), definition=function(object, input) {
solver <- input$solver
problemInstance <- g_problemInstance(object)
if ( !g_hasPrimSupps(problemInstance) ) {
return(object)
}
dimInfo <- g_dimInfo(object)
nrVars <- g_nrVars(problemInstance)
freqs <- g_freq(problemInstance)
primSupps <- g_primSupps(problemInstance)
LPL <- g_LPL(problemInstance)[primSupps]
UPL <- g_UPL(problemInstance)[primSupps]
SPL <- g_SPL(problemInstance)[primSupps]
weights <- g_weight(problemInstance)
HIGH <- LOW <- weights[primSupps]
# order of calculations
myOrder <- order(sapply(1:length(primSupps), function(x) { max(SPL[x], (LPL+UPL)[x]) }), decreasing=TRUE)
LB <- weights - g_lb(problemInstance)
UB <- g_ub(problemInstance) - weights
xi <- g_suppPattern(problemInstance)
res <- c_make_att_prob(input = list(objectA = object))
aProb <- res$aProb
validCuts <- res$newCutsMaster
nrConstraints <- length(g_objective(aProb)) - 2*length(weights)
#validCuts <- init.cutList(type='empty', input=list(nrCols=nrVars))
for ( i in myOrder ) {
if ( i %% 10 == 1 && input$verbose ) {
cat("preprocessing variable",i,"|",length(myOrder),"...\n")
}
cellInd <- primSupps[i]
limits <- c(LPL[i], UPL[i], SPL[i])
# solveAttackerProblem (upper bound)
rhs <- rep(0, length(g_rhs(aProb)))
rhs[cellInd] <- 1
s_rhs(aProb) <- list(rhs)
s_objective(aProb) <- list(c(weights + UB*xi, -(weights-xi*LB), rep(0, nrConstraints)))
up <- c_solve_problem(aProb, input=list(solver))
if ( up$status != 0 ) {
stop("unsolvable problem (up)!\n")
}
calcUp <- up$optimum
HIGH[i] <- max(HIGH[i], calcUp)
LOW[i] <- min(LOW[i], calcUp)
# solveAttackerProblem (lower bound)
s_rhs(aProb) <- list(-1*rhs)
down <- c_solve_problem(aProb, input=list(solver))
if ( down$status != 0 ) {
stop("unsolvable problem (down)!\n")
}
calcDown <- -down$optimum
HIGH[i] <- max(HIGH[i], calcDown)
LOW[i] <- min(LOW[i], calcDown)
alpha.down <- down$solution[1:nrVars]
alpha.up <- up$solution[1:nrVars]
beta.down <- down$solution[(nrVars+1):(2*nrVars)]
beta.up <- up$solution[(nrVars+1):(2*nrVars)]
if ( limits[1] != 0 ) { # LPL
v <- alpha.down*UB + beta.down*LB
v[which(is.zero(v))] <- 0
if ( any(v > 0) )
s_add_complete_constraint(validCuts) <- list(init.cutList(type='singleCut', input=list(vals=v, dir=">=", rhs=limits[1])))
}
if ( limits[2] != 0 ) { # UPL
v <- alpha.up*UB + beta.up*LB
v[which(is.zero(v))] <- 0
if ( any(v > 0) )
s_add_complete_constraint(validCuts) <- list(init.cutList(type='singleCut', input=list(vals=v, dir=">=", rhs=limits[2])))
}
if ( limits[3] != 0 & calcUp - calcDown < limits[3] ) { # SPL
v <- (alpha.down+alpha.up)*UB + (beta.down+beta.up)*LB
v[which(is.zero(v))] <- 0
if ( any(v > 0) )
s_add_complete_constraint(validCuts) <- list(init.cutList(type='singleCut', input=list(vals=v, dir=">=", rhs=limits[3])))
}
}
if ( g_nr_constraints(validCuts) > 0 ) {
validCuts <- c_strengthen(validCuts)
setZeroUPL <- which(freqs[primSupps]+UPL <= HIGH) # -> set UPL = 0
setZeroLPL <- which(freqs[primSupps]-LPL >= LOW) # -> set LPL = 0
setZeroSPL <- which(HIGH-LOW >= SPL ) # -> set SPL = 0
if ( length(setZeroUPL) > 0 ) {
UPL[setZeroUPL] <- 0
s_UPL(problemInstance) <- list(index=primSupps, vals=UPL)
}
if ( length(setZeroLPL) > 0 ) {
LPL[setZeroLPL] <- 0
s_LPL(problemInstance) <- list(index=primSupps, vals=LPL)
}
if ( length(setZeroSPL) > 0 ) {
SPL[setZeroSPL] <- 0
s_SPL(problemInstance) <- list(index=primSupps, vals=SPL)
}
}
s_problemInstance(object) <- problemInstance
return(list(sdcProblem=object, aProb=aProb, validCuts=validCuts))
})
setMethod("c_finalize", signature=c("sdcProblem", "list"), definition=function(object, input) {
Freq <- NULL
pI <- g_problemInstance(object)
dI <- g_dimInfo(object)
sdcStatus <- NULL
out <- sdcProb2df(
obj = object,
addDups = TRUE,
addNumVars = TRUE,
dimCodes = "original"
)
out[sdcStatus == "z", sdcStatus := "s"]
# order
cols <- c(slot(dI, "vNames"), "freq", g_numvar_names(slot(object, "dataObj")), "sdcStatus")
data.table::setcolorder(out, cols)
data.table::setnames(out, old = "freq", new = "Freq")
attr(out, "supp_method") <- input$method
attr(out, "nr_nondup") <- g_nrVars(slot(object, "problemInstance"))
class(out) <- unique(c("safeObj", class(out)))
object@results <- out
return(object)
})
setMethod("c_ghmiter_diag_obj", signature=c("sdcProblem", "list"), definition=function(object, input) {
cellToProtect <- input[[1]]
indexList <- input[[2]]
allowZeros <- input[[3]]
if ( length(cellToProtect) != 1 ) {
stop("makeDiagObj:: length of 'cellToProtect' must equal 1!\n")
}
pI <- g_problemInstance(object)
nrVars <- g_nrVars(pI)
if ( !cellToProtect %in% 1:nrVars ) {
stop("makeDiagObj:: 'cellToProtect' must be >= 1 and <= ",nrVars,"!\n")
}
if ( !cellToProtect %in% 1:nrVars ) {
stop("makeDiagObj:: 'cellToProtect' must be >= 1 and <= ",nrVars,"!\n")
}
sdcStatus <- g_sdcStatus(pI)
if ( allowZeros == TRUE ) {
indZeros <- which(sdcStatus=="z" & g_freq(pI)==0)
if ( length(indZeros ) > 0 ) {
sdcStatus[indZeros] <- "s"
}
}
indToProtect <- sapply(indexList, function(x) { x[cellToProtect] } )
diagIndices <- NULL
for ( i in seq_along(indexList) ) {
if ( length(unique(indexList[[i]])) > 1 ) {
if ( is.null(diagIndices) ) {
diagIndices <- which(indexList[[i]] != indexList[[i]][cellToProtect])
} else {
diagIndices <- intersect(diagIndices, which(indexList[[i]] != indexList[[i]][cellToProtect]))
}
}
}
diagIndices <- diagIndices[which(sdcStatus[diagIndices]!="z")]
if ( length(diagIndices) == 0 )
diagIndices <- NULL
supp <- list()
supp$cellToProtect <- cellToProtect
supp$indToProtect <- indToProtect
supp$diagIndices <- diagIndices
return(supp)
})
setMethod("c_ghmiter_calc_info", signature=c("sdcProblem", "list"), definition=function(object, input) {
# calculate some info on a given quader (normalization,...)
calcQInfo <- function(g, d) {
if ( length(g) != length(d) ) {
stop("calcQInfo: 'g' and 'd' must have equal length!\n")
}
numberIndexVars <- length(g)
quader <- expand(lapply(1:numberIndexVars, function(x) { c(g[x],d[x]) } ), vector=FALSE)
quader <- matrix(unlist(quader), length(quader[[1]]), length(quader))
quader <- quader[!duplicated(quader),,drop=FALSE]
quader <- lapply(1:ncol(quader), function(x) quader[,x])
### normquader
normQ <- list()
for ( i in seq_along(quader) ) {
normQ[[i]] <- rep(0, length(quader[[1]]))
normQ[[i]][which(quader[[i]]==g[i])] <- 1
}
### g|u indication?
indexing <- rep("g", length(quader[[1]]))
indexing[which(apply(matrix(unlist(normQ),length(quader[[1]]),numberIndexVars),1,sum) %%2 != 0)] <- "u"
return(list(quader=quader, normQ=normQ, indexing=indexing))
}
diagObj <- input[[1]]
indexList <- input[[2]]
protectionLevel <- input[[3]]
allowZeros <- input[[4]]
# TODO: error checking
pI <- g_problemInstance(object)
freqs <- g_freq(pI)
sdcStatus <- g_sdcStatus(pI)
if ( allowZeros == TRUE ) {
indZeros <- which(sdcStatus=="z" & g_freq(pI)==0)
if ( length(indZeros ) > 0 ) {
sdcStatus[indZeros] <- "s"
}
}
### relevant Indices ### TODO FIXME CHECK!!!!
relevantIndices <- which(sapply(indexList, function(x) { length(unique(x)) } ) > 1)
resultObj <- list()
# FIXME: What is with 1-dimensional data?
limit <- length(diagObj$diagIndices)
for ( z in 1:limit ) {
g <- diagObj$indToProtect
d <- sapply(indexList, function(x) { x[diagObj$diagIndices[z]] } )
qInfo <- calcQInfo(g, d)
# 2) position (indices==qPosition) of current quader in subTabObj
valsQ <- pasteStrVec(unlist(qInfo$quader), length(qInfo$quader), coll=NULL)
qPosition <- match(valsQ, g_strID(pI))
suppStatus <- sdcStatus[qPosition]
if ( !any(suppStatus == "z") ) {
# 3) calculate various information about the selected quader (infoQuader)
# 3.1) how many values would need to be suppressed for this quader
indNonSupp <- which(sdcStatus[qPosition] == "s" & sdcStatus[qPosition] != "u")
nrAdditionalSupps <- length(indNonSupp)
# 3.2) whats the amount of information which needs to be suppressed?
sumAdditionalSuppsFreq <- sum(freqs[qPosition[indNonSupp]])
# 3.3) does the quader contains other single cells except for
# the primary suppressed value (diaObj$cellToPretect) to check?
# subIndices = current quader without primary suppressed cell to check
indSingleItems <- setdiff(which(freqs[qPosition]==1),1)
singleItems <- NULL
indikatorSingleItems <- FALSE
if( length(indSingleItems) >= 1 ) {
indikatorSingleItems <- TRUE
singleItems <- indSingleItems
}
# 3.5) is the quader protected enough? (protectionLevel)
# we need to check for interval-protection only if protectionLevel > 0
schutzInd <- TRUE
schutz <- protectionLevel
# FIXME: S|P (what to do with "x" that are temporarily "u"?)
if( protectionLevel > 0 ) {
if ( !all(qInfo$indexing =="u") ) {
range <- min(freqs[qPosition[which(qInfo$indexing =="u")]], na.rm=TRUE) + min(freqs[qPosition[which(qInfo$indexing =="g")]], na.rm=TRUE)
X <- freqs[diagObj$cellToProtect]
if( X == 0 ) {
tmpInd <- which(sdcStatus[qPosition] != "u" & freqs[qPosition] != 0)
if( length(tmpInd) > 0 ) {
# TODO: this needs testing !!! (page 60, repsilber)
if( range <= min(freqs[tmpInd]) ) {
schutzInd <- FALSE
protectionLevel <- 0
}
}
}
else {
schutz <- (100*range) / X
if ( schutz < protectionLevel )
schutzInd <- FALSE
}
}
}
# 4) return results
# in this case, the cell is already protected, so we can stop!
# allowZeros==TRUE: we have not found patterns without zeros
# so we do not care for an 'optimal' solution that does not exist anyway
if ( allowZeros == TRUE ) {
if ( length(resultObj) == 100 ) {
return(resultObj)
break
}
} else {
if( nrAdditionalSupps == 0 & schutzInd == TRUE & indikatorSingleItems == FALSE ) {
return(erg = NULL)
break
}
}
resultObj[[length(resultObj)+1]] <- list(
quaderStrID = valsQ,
indexing = qInfo$indexing,
qPosition = qPosition,
nrAdditionalSupps=nrAdditionalSupps,
sumAdditionalSuppsFreq = sumAdditionalSuppsFreq,
indikatorSingleItems = indikatorSingleItems,
singleItems = singleItems,
schutz = schutz,
schutzInd = schutzInd
)
}
}
return(resultObj)
})
setMethod("c_ghmiter_suppress_quader", signature=c("sdcProblem", "list"), definition=function(object, input) {
pI <- g_problemInstance(object)
sdcStatus <- g_sdcStatus(pI)
suppIndex <- setdiff(input$qPosition, input$qPosition[which(sdcStatus[input$qPosition]=="u")])
s_sdcStatus(pI) <- list(index=suppIndex, vals=rep("x", length(suppIndex)))
s_problemInstance(object) <- pI
return(object)
})
setMethod("c_ghmiter_select_quader", signature=c("sdcProblem", "list"), definition=function(object, input) {
infoObj <- input[[1]]
suppMethod <- input[[2]]$suppMethod
verbose <- input[[2]]$verbose
sdcStatus <- g_sdcStatus(g_problemInstance(object))
relevantIndices <- as.numeric(unlist(lapply(infoObj, '[', 'schutzInd'))[1])
# already protected
if ( is.null(infoObj) ) {
suppObj <- NULL
return(suppObj)
}
# not protected yet
# which elements of iqsInfo are NULL?
nullElements <- which(unlist(lapply(lapply(infoObj, '[[', 'qPosition'), function(x) { length(x) } )) == 0)
if ( length(nullElements) > 0 ) {
infoObj <- infoObj[-nullElements]
}
# put iqs together so that we can choose the optimal suppression scheme
qIndexNr <- 1:length(infoObj)
nrAdditionalSupps <- as.numeric(unlist(lapply(infoObj, '[', 'nrAdditionalSupps')))
sumAdditionalSuppsFreq <- as.numeric(unlist(lapply(infoObj, '[', 'sumAdditionalSuppsFreq')))
indikatorSingleItems <- as.logical(unlist(lapply(infoObj, '[', 'indikatorSingleItems')))
schutz <- as.numeric(unlist(lapply(infoObj, '[', 'schutz')))
schutzInd <- as.logical(unlist(lapply(infoObj, '[', 'schutzInd')))
schutzInd <- as.logical(unlist(lapply(infoObj, '[', 'schutzInd')))
possQuaders <- data.frame(qIndexNr, nrAdditionalSupps, sumAdditionalSuppsFreq, indikatorSingleItems, schutz, schutzInd)
# are there any suppression schemes satisfying the necessary interval protection?
indexIntervallOk <- FALSE
if ( any(possQuaders$schutzInd==TRUE) )
indexIntervallOk <- TRUE
# do suppression schemes exist that do not contain single values?
# these are preferred suppression schemes.
existNonSingles <- FALSE
if ( any(possQuaders$indikatorSingleItems == FALSE) ) {
existNonSingles <- TRUE
possQuaders <- possQuaders[possQuaders$indikatorSingleItems==FALSE,,drop=FALSE]
}
if( indexIntervallOk ) {
if ( min(possQuaders$nrAdditionalSupps) > 0 & verbose == TRUE) {
cat("# additional secondary Supps:", min(possQuaders$nrAdditionalSupps)," ")
}
if ( suppMethod == "minSupps" ) {
possQuaders <- possQuaders[which(possQuaders$nrAdditionalSupps == min(possQuaders$nrAdditionalSupps)),,drop=FALSE]
possQuaders <- possQuaders[which(possQuaders$sumAdditionalSuppsFreq == min(possQuaders$sumAdditionalSuppsFreq)),,drop=FALSE]
}
if ( suppMethod == "minSum" ) {
possQuaders <- possQuaders[which(possQuaders$sumAdditionalSuppsFreq == min(possQuaders$sumAdditionalSuppsFreq)),,drop=FALSE]
possQuaders <- possQuaders[which(possQuaders$nrAdditionalSupps == min(possQuaders$nrAdditionalSupps)),,drop=FALSE]
}
if ( suppMethod == "minSumLogs" ) {
possQuaders <- possQuaders[which(possQuaders$sumAdditionalSuppsFreq == min(log(1+possQuaders$sumAdditionalSuppsFreq))),,drop=FALSE]
possQuaders <- possQuaders[which(possQuaders$nrAdditionalSupps == min(possQuaders$nrAdditionalSupps)),,drop=FALSE]
}
# finally choose the suppression scheme
possQuaders <- possQuaders[1,]
suppObj <- infoObj[[possQuaders$qIndexNr]]
}
# problem: no suppression scheme is satisfying the
# required interval protection
else {
# all cells in this subtable are already suppressed
# -> everything is ok
if( all(sdcStatus=="u" | sdcStatus == "x") )
suppObj <- NULL
# no suppression scheme satisfies the required interval protection
# the suppression pattern with the max. protection level is selected
else {
possQuaders <- possQuaders[which(possQuaders$schutz == max(possQuaders$schutz)),]
possQuaders <- possQuaders[which(possQuaders$nrAdditionalSupps == min(possQuaders$nrAdditionalSupps)),]
possQuaders <- possQuaders[which(possQuaders$sumAdditionalSuppsFreq == min(possQuaders$sumAdditionalSuppsFreq)),]
possQuaders <- possQuaders[1,]
suppObj <- infoObj[[possQuaders$qIndexNr]]
}
}
return(suppObj)
})
setMethod("c_ghmiter_supp_additional", signature=c("sdcProblem", "list"), definition=function(object, input) {
diagObj <- input[[1]]
infoObj <- input[[2]]
suppObj <- input[[3]]
suppMethod <- input[[4]]$suppMethod
verbose <- input[[4]]$suppMethod
### Task: find quader (from) infoObj with following restrictions
freqs <- g_freq(g_problemInstance(object))
# - must not be suppObj itself
cellToProtect <- diagObj$cellToProtect
suppIndicesOrig <- suppObj$qPosition
# the additional quader must non contain these indices
# the singletons in the original suppressed pattern
prohibitedIndices <- setdiff(suppIndicesOrig[which(freqs[suppIndicesOrig] == 1)],cellToProtect)
# the possible indices
possIndices <- lapply(infoObj, function(x) { x$qPosition } )
# do the indices of the possible patterns contain any of the prohibited cells
res <- sapply(1:length(possIndices), function(x) { any(prohibitedIndices %in% possIndices[[x]]) } )
if ( all(res == TRUE ) ) {
#warning("no additional cube could be found!\n")
infoObj <- NULL
} else {
ind <- which(res==TRUE)
infoObj <- infoObj[-ind]
}
suppObjNew <- c_ghmiter_select_quader(object, input=list(infoObj, input[[4]]))
if ( !is.null(suppObjNew) ) {
object <- c_ghmiter_suppress_quader(object, input=suppObjNew)
}
return(object)
})
setMethod("c_reduce_problem", signature=c("sdcProblem", "list"), definition=function(object, input) {
x <- object
y <- input[[1]]
pI <- g_problemInstance(x)
dimInfo <- g_dimInfo(x)
strInfo <- strInfoOrig <- g_str_info(dimInfo)
dim_names <- slot(dimInfo, "vNames")
if (length(y) < 1) {
stop("c_reduce_problem:: length of argument 'y' < 1!", call. = FALSE)
}
if (!all(y %in% 1:g_nrVars(pI))) {
stop("c_reduce_problem:: elements of indices y does not match with problem size!", call. = FALSE)
}
newDims <- lapply(1:length(strInfo), function(x) {
substr(g_strID(pI)[y], strInfo[[x]][1], strInfo[[x]][2])
})
newDims2 <- lapply(1:length(newDims), function(x) {
sort(unique(newDims[[x]]))
})
newDimsOrigCodes <- lapply(1:length(newDims), function(k) {
c_match_orig_codes(object = dimInfo@dimInfo[[k]], input = newDims2[[k]])
})
lenNewDims <- sapply(newDims2, length) - 1
codesNew <- lapply(1:length(newDims), function(x) {
c("@", rep("@@", lenNewDims[x]))
})
dimInfoOld <- lapply(1:length(newDims2), function(x) {
init.dimVar(input = list(
input = data.frame(codesNew[[x]], newDims2[[x]]), vName = dim_names[x])
)
})
dimInfoNew <- lapply(1:length(newDims2), function(x) {
init.dimVar(input = list(
input = data.frame(codesNew[[x]], newDimsOrigCodes[[x]]), vName = dim_names[x])
)
})
new.codes <- lapply(1:length(newDims), function(x) {
dimInfoOld[[x]]@codesDefault[match(newDims[[x]], dimInfoOld[[x]]@codesOriginal)]
})
pI@strID <- pasteStrVec(unlist(new.codes), length(newDims))
pI@Freq <- g_freq(pI)[y]
if (!is.null(g_w(pI))) {
pI@w <- g_w(pI)[y]
}
numVars <- as.list(g_numVars(pI))
if (length(numVars) > 0) {
for (j in 1:length(numVars)) {
pI@numVars[[j]] <- numVars[[j]][y]
}
}
pI@lb <- g_lb(pI)[y]
pI@ub <- g_ub(pI)[y]
pI@LPL <- g_LPL(pI)[y]
pI@UPL <- g_UPL(pI)[y]
pI@SPL <- g_SPL(pI)[y]
pI@sdcStatus <- g_sdcStatus(pI)[y]
x@dimInfo@dimInfo <- dimInfoNew
# strInfo
info <- c(0, cumsum(sapply(1:length(codesNew), function(x) {
sum(sapply(table(codesNew[[x]]), nchar))
})))
for (i in 2:length(info)) {
strInfo[[i - 1]] <- c(info[i - 1] + 1, info[i])
}
x@dimInfo@strInfo <- strInfo
s_problemInstance(x) <- pI
validObject(x)
return(x)
})
setMethod("c_gen_structcuts", signature=c("sdcProblem", "list"), definition=function(object, input) {
pI <- g_problemInstance(object)
dimInfoObj <- g_dimInfo(object)
partition <- c_make_partitions(input=list(objectA=pI, objectB=dimInfoObj))
dimInfo <- g_dim_info(dimInfoObj)
nrLevels <- length(dimInfo)
nrVars <- g_nrVars(pI)
primSupps <- g_primSupps(pI)
strIDs <- g_strID(pI)
indices <- partition$indices
weights <- g_weight(pI)
requiredCuts <- init.cutList(type='empty', input=list(nrCols=nrVars))
strInfo <- g_str_info(dimInfoObj)
x <- rep(0, nrVars)
for ( z in seq_along(primSupps) ) {
pSupp <- primSupps[z]
currentPrimSupp <- strIDs[pSupp]
matchInd <- unlist(lapply(1:length(indices), function(x) {
lapply(1:length(indices[[x]]), function(y) {
if ( !all(is.na(match(pSupp, indices[[x]][[y]]))) ) {c(x,y)}
})
}))
if ( any(is.na(matchInd)) ) {
stop('elements of matchInd must not be NA!\n')
}
splitMatchInd <- split(matchInd, rep(1:(length(matchInd)/2), each=2))
for ( u in 1:length(splitMatchInd) ) {
matchInd <- splitMatchInd[[u]]
nrPow <- nrLevels - length(which(as.numeric(unlist(strsplit(partition$groups[[matchInd[1]]],"-")))==1))
v1 <- v2 <- x
index <- indices[[matchInd[1]]][[matchInd[2]]]
v1[index] <- weights[index]
v2[index] <- 1
lim <- sum(sort(weights[index])[1:(2^nrPow)])
if ( any(v1 != 0) ) {
s_add_complete_constraint(requiredCuts) <- list(init.cutList(type='singleCut', input=list(vals=v1, dir=">=", rhs=lim)))
}
if ( any(v2 != 0) ) {
s_add_complete_constraint(requiredCuts) <- list(init.cutList(type='singleCut', input=list(vals=v2, dir=">=", rhs=(2^nrPow))))
}
### Todo: at least 2 suppressions in each dimension
### there is some error here! -> TODO: CHECK: FIXME!
#for ( i in 1:length(dimInfo) ) {
# lO <- dimInfo[[i]]
# splitList <- lapply(strInfo[i], function(k) { seq(k[1], k[2]) } )
# subStringToFix <- mySplitIndicesList(currentPrimSupp, splitList)
# f <- mySplitIndicesList(strIDs, splitList)
#
# index <- which(f == subStringToFix)
# v3 <- x
# v4 <- x
# v3[index] <- weights[index]
# v4[index] <- 1
# lim <- sum(sort(weights[index])[1:2])
# if ( any(v3 != 0) ) {
# if ( !is.na(lim) ) {
# s_add_complete_constraint(requiredCuts) <- list(init.cutList(type='singleCut', input=list(vals=v3, dir=">=", rhs=lim)))
# }
# }
# if ( any(v4 != 0) ) {
# s_add_complete_constraint(requiredCuts) <- list(init.cutList(type='singleCut', input=list(vals=v4, dir=">=", rhs=2)))
# }
#}
}
}
dupRows <- g_duplicated_rows(g_constraints(requiredCuts))
if ( length(dupRows) > 0 ) {
s_remove_complete_constraint(requiredCuts) <- list(dupRows)
}
return(requiredCuts)
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.