// $Id$ #include "flopc.hpp" using namespace flopc; using namespace std; #include "OsiCbcSolverInterface.hpp" #include "CoinFloatEqual.hpp" namespace Aircraft { enum {a, b, c, d, numA}; } int main() { /*The objective of this model is to allocate aircrafts to routes to maximize the expected profit when traffic demand is uncertain. Two different formulations are used, the delta and the lambda formualation. Dantzig, G B, Chapter 28. In Linear Programming and Extensions. Princeton University Press, Princeton, New Jersey, 1963. */ { enum {route_1, route_2, route_3, route_4, route_5, numRoutes}; const int numDemandStates = 5; MP_set i(Aircraft::numA); // aircraft types and unassigned passengers MP_set j(numRoutes); // assigned and unassigned routes MP_set h(numDemandStates);// demand states double ddval[5][5] = {{200, 220, 250, 270, 300}, { 50, 150, 0, 0, 0}, {140, 160, 180, 200, 220}, { 10, 50, 80, 100, 340}, {580, 600, 620, 0, 0}}; double lambdaval[5][5] = {{.2, .05, .35, .2, .2}, {.3, .7, 0.0, 0.0, 0.0}, {.1, .2, .4, .2, .1}, {.2, .2, .3, .2, .1}, {.1, .8, .1, 0.0, 0.0}}; double cval[4][5] = {{18, 21, 18, 16, 10}, {0, 15, 16, 14, 9}, {0, 10, 0, 9, 6}, {17, 16, 17, 15, 10}}; double pval[4][5] = {{16, 15, 28, 23, 81}, {0, 10, 14, 15, 57}, {0, 5, 0, 7, 29}, {9, 11, 22, 17, 55}}; MP_data dd(&ddval[0][0],j,h); // dd.value(&ddval[0][0]); MP_data lambda(&lambdaval[0][0],j,h); //lambda.value(&lambdaval[0][0]); MP_data c(&cval[0][0],i,j); // c.value(&cval[0][0]); MP_data p(&pval[0][0],i,j); // p.value(&pval[0][0]); c.display("c"); MP_data aa(i), // aircraft availiability k(j), // revenue lost (1000 per 100 bumped) ed(j), // expected demand gamma(j,h), // probability of exceeding demand increment h on route j deltb(j,h); // incremental passenger load in demand states; aa(Aircraft::a) = 10; aa(Aircraft::b) = 19; aa(Aircraft::c) = 25; aa(Aircraft::d) = 15; k(route_1) = 13; k(route_2) = 13; k(route_3) = 7; k(route_4) = 7; k(route_5) = 1; ed(j) = sum(h, lambda(j,h)*dd(j,h)); MP_index hp; gamma(j,h) = sum( h(hp).such_that(hp >= h), lambda(j,hp)); deltb(j,h) = pos(dd(j,h)-dd(j,h-1)); ed.display("ed"); gamma.display("gamma"); deltb.display("deltb"); aa.display("aa"); MP_variable x(i,j), // number of aircraft type i assigned to route j y(j,h), // passengers actually carried b(j,h), // passengers bumped oc, // operating cost bc; // bumping cost MP_constraint ab(i), // aircraft balance db(j), // demand balance yd(j,h), // definition of boarded passangers bd(j,h), // definition of bumped passangers ocd, // bcd1, // bumping cost definition: version 1 bcd2; // bumping cost definition: version 2 ab(i) = sum(j, x(i,j)) <= aa(i); ab.setName("aircraft balance"); db(j) = sum(i, p(i,j)*x(i,j)) >= sum( h.such_that(deltb(j,h)>0), y(j,h)); db.setName("demand balance"); yd(j,h) = y(j,h) <= sum(i, p(i,j)*x(i,j)); yd.setName("definition of boarded passengers"); bd(j,h) = b(j,h) == dd(j,h) - y(j,h); bd.setName("definition of bumped passengers"); ocd() = oc() == sum(i*j, c(i,j)*x(i,j)); bcd1() = bc() == sum(j, k(j)*(ed(j)-sum(h, gamma(j,h)*y(j,h)))); bcd2() = bc() == sum(j*h, k(j)*lambda(j,h)*b(j,h)); MP_model m1(new OsiCbcSolverInterface), m2(new OsiCbcSolverInterface); y.upperLimit(j,h) = deltb(j,h); y.upperLimit.display("y upper"); m1.add(ab).add(db).add(bcd1).add(ocd); m1.minimize(oc() + bc()); assert(m1->getNumRows()==11); assert(m1->getNumCols()==47); assert(m1->getNumElements()==96); assert(m1->getObjValue()>=1566.03 && m1->getObjValue()<=1566.05); y.display("y first model"); ab.display("ab"); db.display("db"); bcd1.display("bcd1"); ocd.display("ocd"); m2.add(ab).add(yd).add(bd).add(bcd2).add(ocd); y.upperLimit(j,h) = m2->getInfinity(); m2.minimize(oc() + bc()); assert(m2->getNumRows()==56); assert(m2->getNumCols()==72); assert(m2->getNumElements()==219); // Optimal objective value m1: 1566.04 // Optimal objective value m2: 1566.04 (like m1) assert(m2->getObjValue()>=1566.03 && m2->getObjValue()<=1566.05); CoinRelFltEq eq(1.e-05); #ifndef NDEBUG double m1ObjValue=m1->getObjValue(); double m2ObjValue=m2->getObjValue(); #endif assert( eq(m2ObjValue,1566.04) ); assert( eq(m1ObjValue,1566.04) ); y.display("y second model"); } cout<<"All tests completed successfully"<