| 254 | } |
| 255 | |
| 256 | void MILPEncoder::encodeMaxConstraint( GurobiWrapper &gurobi, MaxConstraint *max, bool relax ) |
| 257 | { |
| 258 | if ( !max->isActive() ) |
| 259 | return; |
| 260 | |
| 261 | List<GurobiWrapper::Term> terms; |
| 262 | List<PhaseStatus> phases = max->getAllCases(); |
| 263 | for ( unsigned i = 0; i < phases.size(); ++i ) |
| 264 | { |
| 265 | // add a binary variable for each disjunct |
| 266 | gurobi.addVariable( Stringf( "a%u_%u", _binVarIndex, i ), |
| 267 | 0, |
| 268 | 1, |
| 269 | relax ? GurobiWrapper::CONTINUOUS : GurobiWrapper::BINARY ); |
| 270 | |
| 271 | terms.append( GurobiWrapper::Term( 1, Stringf( "a%u_%u", _binVarIndex, i ) ) ); |
| 272 | } |
| 273 | |
| 274 | // add constraint: a_1 + a_2 + ... + = 1 |
| 275 | gurobi.addEqConstraint( terms, 1 ); |
| 276 | |
| 277 | terms.clear(); |
| 278 | unsigned index = 0; |
| 279 | for ( const auto &phase : phases ) |
| 280 | { |
| 281 | String binVarName = Stringf( "a%u_%u", _binVarIndex, index ); |
| 282 | PiecewiseLinearCaseSplit split = max->getCaseSplit( phase ); |
| 283 | if ( phase == MAX_PHASE_ELIMINATED ) |
| 284 | { |
| 285 | /* |
| 286 | We had y - eliminated value >= 0 |
| 287 | We add y - eliminated-value <= (1 - a) * (ub_y - eliminated-value), |
| 288 | which becomes y + (ub_y - eliminated-value) * a <= ub_y |
| 289 | */ |
| 290 | unsigned y = split.getBoundTightenings().begin()->_variable; |
| 291 | double yUb = _tableau.getUpperBound( y ); |
| 292 | double eliminatedValue = split.getBoundTightenings().begin()->_value; |
| 293 | |
| 294 | terms.append( GurobiWrapper::Term( 1, Stringf( "x%u", y ) ) ); |
| 295 | terms.append( GurobiWrapper::Term( yUb - eliminatedValue, binVarName ) ); |
| 296 | gurobi.addLeqConstraint( terms, yUb ); |
| 297 | } |
| 298 | else |
| 299 | { |
| 300 | /* |
| 301 | We added aux_i >= 0, for each x. |
| 302 | We now add, aux_i <= (1 - a) * (ub_aux) |
| 303 | */ |
| 304 | DEBUG( { |
| 305 | ASSERT( split.getBoundTightenings().size() == 1 ); |
| 306 | ASSERT( split.getEquations().size() == 0 ); |
| 307 | } ); |
| 308 | unsigned aux = split.getBoundTightenings().begin()->_variable; |
| 309 | double auxUb = _tableau.getUpperBound( aux ); |
| 310 | terms.append( GurobiWrapper::Term( 1, Stringf( "x%u", aux ) ) ); |
| 311 | terms.append( GurobiWrapper::Term( auxUb, binVarName ) ); |
| 312 | gurobi.addLeqConstraint( terms, auxUb ); |
| 313 | } |
nothing calls this directly
no test coverage detected