void binmap(int *rule, // 1 or 2, just like for approx() double *beamAngle, double *pitch, double *roll, // all of length 1 int *n, // length of distance, z1-z4, and y1-y4 double *distance, // like "x" double *y1, double *y2, double *y3, double *y4, // like a set of "y" values // below are storage double *buffer, // do not allocate locally, for speed double *z1, double *z2, double *z3, double *z4, // calculated here; just supply space double *Y1, double *Y2, double *Y3, double *Y4) // calculated here; just supply space { int i; // distance, y, y1-y4 are of length *n // beamAngle, pitch, and roll are of length 1 const double RPD = atan2(1.0, 1.0) / 45.0; // radians/degree #if 0 Rprintf("n %d\n", *n); Rprintf("beamAngle %f pitch %f roll %f\n", *beamAngle, *pitch, *roll); #endif double cr = cos((*roll) * RPD); double sr = sin((*roll) * RPD); double cp = cos((*pitch) * RPD); double sp = sin((*pitch) * RPD); double tt = tan((*beamAngle) * RPD); #if 0 Rprintf("C : r %.6f p %.6f cr %.6f sr %.6f cp %.6f sp %.6f tt %.6f\n", *roll, *pitch, cr, sr, cp, sp, tt); #endif for (i=0; i < *n; i++) { z1[i] = distance[i] * (cr - tt * sr) * cp; z2[i] = distance[i] * (cr + tt * sr) * cp; z3[i] = distance[i] * (cp + tt * sp) * cr; z4[i] = distance[i] * (cp - tt * sp) * cr; } #if 0 Rprintf("C : z1 "); for (i = 0; i < 8; i++) Rprintf("%11.6f ", i, z1[i]); Rprintf("\n"); #endif // y <- .C(C_R_approx, as.double(x), as.double(y), as.integer(nx), // xout = as.double(xout), as.integer(length(xout)), as.integer(method), // as.double(yleft), as.double(yright), as.double(f), NAOK = TRUE, // PACKAGE = "stats")$xout double f = 0.0; // unused, since we set method=1; see docs on approx() double left, right; // void R_approx(double *x, double *y, int *nxy, double *xout, int *nout, // int *method, double *yleft, double *yright, double *f) // NOTE: replaces xout with the interpolated value! int method = 1; // "linear" for approx() if (*rule == 1) { left = NA_REAL; right = NA_REAL; } else { left = y1[0]; right = y1[*n]; } for (i = 0; i < *n; i++) { buffer[i] = distance[i]; } R_approx(z1, y1, n, buffer, n, &method, &left, &right, &f); for (i = 0; i < *n; i++) { Y1[i] = buffer[i]; buffer[i] = distance[i]; } if (*rule == 1) { left = NA_REAL; right = NA_REAL; } else { left = y2[0]; right = y2[*n]; } R_approx(z2, y2, n, buffer, n, &method, &left, &right, &f); for (i = 0; i < *n; i++) { Y2[i] = buffer[i]; buffer[i] = distance[i]; } if (*rule == 1) { left = NA_REAL; right = NA_REAL; } else { left = y3[0]; right = y3[*n]; } R_approx(z3, y3, n, buffer, n, &method, &left, &right, &f); for (i = 0; i < *n; i++) { Y3[i] = buffer[i]; buffer[i] = distance[i]; } if (*rule == 1) { left = NA_REAL; right = NA_REAL; } else { left = y4[0]; right = y4[*n]; } R_approx(z4, y4, n, buffer, n, &method, &left, &right, &f); for (i = 0; i < *n; i++) { Y4[i] = buffer[i]; } }
int main(int argc, char **argv) { clock_t t1, t2; t1 = clock(); IloEnv env; IloModel model(env); IloCplex cplex(model); /************************** Defining the parameters ************************************/ IloInt N; //No. of nodes IloInt M; //No. of calls Num2DMatrix links(env); //Defines the topology of the network IloNumArray call_demand(env); //link bandwidth requirement of each call IloNumArray call_revenue(env); //revenue generated from the call IloNumArray call_origin(env); //origin node index of each call IloNumArray call_destination(env); //destination node index of each call Num2DMatrix Q(env); //Bandwidth capacity of each link Num2DMatrix sigma(env); //Standard deviation of service times on link (i,j) Num2DMatrix cv(env); //coefficient of variation of service times on the link (i,j) IloNum C; //Unit queueing delay cost per unit time IloNumArray R_approx_init(env); ifstream fin; const char* filename = "BPP_data_sample - Copy.txt"; if (argc > 1) filename = argv[1]; fin.open(filename); //fin.open("BPP_10node_navneet.txt"); fin >> links >> call_origin >> call_destination >> call_demand >> call_revenue >> Q >> cv >> R_approx_init >> C ; cout << "Reading Data from the file - "<<filename<<endl; N = links.getSize(); M = call_origin.getSize(); IloInt H = R_approx_init.getSize(); Num3DMatrix R_approx(env, N); //The tangential linear function approximation to R. for (IloInt i=0; i<N; i++) { R_approx[i] = Num2DMatrix(env, N); for (IloInt j=0; j<N; j++) { R_approx[i][j] = IloNumArray(env, H); for (IloInt h=0; h<H; h++) R_approx[i][j][h] = R_approx_init[h]; } } /************************** Defining the parameters ENDS ************************************/ /************* Defining the variables defined in the model formulation **********************/ IloNumVarArray Y(env, M, 0, 1, ILOINT); //Variable to define whether a call m is routed or not IloNumArray Y_sol(env, M); //Solution values NumVar3DMatrix X(env, N); //Variable to define whether a call m is routed along path i-j Num3DMatrix X_sol(env, N); for (IloInt i=0; i<N; i++) { X[i] = NumVar2DMatrix(env, N); X_sol[i] = Num2DMatrix(env, N); for (IloInt j=0; j<N; j++) { X[i][j] = IloNumVarArray(env, M, 0, 1, ILOINT); X_sol[i][j] = IloNumArray(env, M); } } NumVar3DMatrix W(env, N); //Variable to define whether a call m is routed along path i-j for (IloInt i=0; i<N; i++) { W[i] = NumVar2DMatrix(env, N); for (IloInt j=0; j<N; j++) W[i][j] = IloNumVarArray(env, M, 0, 1, ILOINT); } NumVar2DMatrix R(env, (IloInt)N); //The linearization Variable for (IloInt i=0; i<N; i++) R[i] = IloNumVarArray(env, (IloInt)N, 0, IloInfinity, ILOFLOAT); /************* Defining the variables defined in the model formulation ENDS *****************/ /**************************** Defining the Constraints *******************************/ // Constraint #1 : Flow Conservation Constraint for (IloInt m=0; m<M; m++) { for (IloInt i=0; i<N; i++) { IloExpr constraint1(env); for (IloInt j=0; j<N; j++) { if (links[i][j] == 1) constraint1 += W[i][j][m]; } for (IloInt j=0; j<N; j++) { if (links[j][i] == 1) constraint1 += -W[j][i][m]; } if (i == call_origin[m]) model.add(constraint1 == Y[m]); else if (i == call_destination[m]) model.add(constraint1 == -Y[m]); else model.add(constraint1 == 0); constraint1.end(); } } // Constraint #2 : for (IloInt m=0; m<M; m++) { for (IloInt i=0; i<N; i++) { for (IloInt j=0; j<N; j++) { if (links[i][j] == 1) model.add(W[i][j][m] + W[j][i][m] <= X[i][j][m]); } } } // Constraint #3 : Link Capacity Constraint for (IloInt i=0; i<N; i++) { for (IloInt j=i+1; j<N; j++) { if (links[i][j] == 1) { IloExpr constraint3(env); for (IloInt m=0; m<M; m++) constraint3 += call_demand[m]*X[i][j][m]; model.add(constraint3 <= Q[i][j]); constraint3.end(); } } } // Constraint #4 : Defining the constraint for initial values of R_approx, // Cuts must be added during the iterations whenever the values are updated for (IloInt i=0; i<N; i++) { for (IloInt j=i+1; j<N; j++) { if (links[i][j] == 1) { for (IloInt h=0; h<H; h++) { IloExpr constraint4_lhs(env); IloNum constraint4_rhs = 0; for (IloInt m=0; m<M; m++) constraint4_lhs += call_demand[m]*X[i][j][m]; constraint4_lhs -= (Q[i][j]/((1+R_approx[i][j][h])*(1+R_approx[i][j][h])))*R[i][j]; constraint4_rhs = Q[i][j]*((R_approx[i][j][h]/(1+R_approx[i][j][h])) * (R_approx[i][j][h]/(1+R_approx[i][j][h]))); model.add(constraint4_lhs <= constraint4_rhs); constraint4_lhs.end(); } } } } /************************** Defining the Constraints ENDS ****************************/ /************************ Defining the Objective Function ****************************/ IloExpr Objective(env); IloExpr Obj_expr1(env); IloExpr Obj_expr2(env); for (IloInt m=0; m<M; m++) Obj_expr1 += call_revenue[m]*Y[m]; for (IloInt i=0; i<N; i++) { for (IloInt j=i+1; j<N; j++) { if (links[i][j] == 1) { Obj_expr2 += (1+cv[i][j] * cv[i][j])*R[i][j]; for (IloInt m=0; m<M; m++) Obj_expr2 += ((1-cv[i][j] * cv[i][j])/Q[i][j])*call_demand[m]*X[i][j][m]; } } } Objective += Obj_expr1 - 0.5*C*Obj_expr2; model.add(IloMaximize(env, Objective)); //model.add(IloMinimize(env, -Objective)); Objective.end(); Obj_expr1.end(); Obj_expr2.end(); /********************** Defining the Objective Function ENDS **************************/ IloNum eps = cplex.getParam(IloCplex::EpInt); IloNum UB = IloInfinity; IloNum LB = -IloInfinity; /***************** Solve ***********************/ do { cplex.setParam(IloCplex::MIPInterval, 5); cplex.setParam(IloCplex::NodeFileInd ,2); cplex.setOut(env.getNullStream()); cplex.exportModel("BPP_model.lp"); if(!cplex.solve()) { cout << "Infeasible"<<endl; system("pause"); } else { for (IloInt m=0; m<M; m++) { if (cplex.getValue(Y[m]) > eps) { cout << "Call(m) = "<<m+1<<" : "<<call_origin[m]+1<<" --> "<<call_destination[m]+1 <<"; demand = "<<call_demand[m]<<endl; cout << "Path : "; for (IloInt i=0; i<N; i++) { for (IloInt j=i+1; j<N; j++) { if (links[i][j] == 1) { if (cplex.getValue(X[i][j][m]) > eps) { X_sol[i][j][m] = 1; cout <<i+1<<"-"<<j+1<<"; "; } } } } cout << endl << endl; } } //system("pause"); } UB = min(UB, cplex.getObjValue()); IloNum lbound = 0; for (IloInt m=0; m<M; m++) if(cplex.getValue(Y[m]) > eps) lbound += call_revenue[m]; for (IloInt i=0; i<N; i++) { for (IloInt j=i+1; j<N; j++) { if (links[i][j] == 1) { IloNum lbound_temp1 = 0; IloNum lbound_temp2 = 0; for (IloInt m=0; m<M; m++) lbound_temp1 += call_demand[m]*X_sol[i][j][m]; lbound_temp2 = 0.5*(1+cv[i][j]*cv[i][j]) * (lbound_temp1*lbound_temp1) / (Q[i][j]*(Q[i][j]-lbound_temp1)); lbound_temp2 += lbound_temp1 / Q[i][j]; lbound -= C*lbound_temp2; } } } LB = max(LB, lbound); Num2DMatrix R_approx_new(env, N); for (IloInt i=0; i<N; i++) R_approx_new[i] = IloNumArray(env, N); for (IloInt i=0; i<N; i++) { for (IloInt j=i+1; j<N; j++) { if (links[i][j] == 1) { IloExpr cut_lhs(env); IloNum cut_rhs = 0; IloNum cut_temp = 0; for (IloInt m=0; m<M; m++) { cut_temp += call_demand[m]*X_sol[i][j][m]; } R_approx_new[i][j] = cut_temp / (Q[i][j] - cut_temp); //cout << "R_approx_new = "<<R_approx_new<<endl; for (IloInt m=0; m<M; m++) cut_lhs += call_demand[m]*X[i][j][m]; cut_lhs -= (Q[i][j]/((1+R_approx_new[i][j])*(1+R_approx_new[i][j])))*R[i][j]; cut_rhs = Q[i][j]*((R_approx_new[i][j]/(1+R_approx_new[i][j])) * (R_approx_new[i][j]/(1+R_approx_new[i][j]))); model.add(cut_lhs <= cut_rhs); cut_lhs.end(); } } } cout << "UB = "<<UB<<endl; cout << "LB = "<<LB<<endl; cout << "Gap (%) = "<<(UB-LB)*100/LB<<endl; //system("pause"); }while ((UB-LB)/UB > eps); t2 = clock(); float secs = (float)t2 - (float)t1; secs = secs / CLOCKS_PER_SEC; cout << "CPUTIME = "<<secs <<endl<<endl; }