//******************************************************************* CPXLPptr CSolver::LoadProblem(bool bMip) { m_lp = CPXcreateprob (m_env, &m_status, m_pszProbname); CPXchgobjsen (m_env, m_lp, m_nObjSense ); if ( m_status != 0 ) { CPXgeterrorstring(m_env, m_status, m_error ); return 0; } if ( m_status != 0 ) { CPXgeterrorstring(m_env, m_status, m_error ); return 0; } m_status = CPXnewrows( m_env, m_lp, m_nRhsItems, m_pRhs, m_pRhsSense, 0, m_rname); if ( m_status != 0 ) { CPXgeterrorstring(m_env, m_status, m_error ); return 0; } if (!bMip) m_status = CPXnewcols( m_env, m_lp, m_nObjItems, m_pObj, m_pBdl, m_pBdu, NULL, m_cname); else m_status = CPXnewcols( m_env, m_lp, m_nObjItems, m_pObj, m_pBdl, m_pBdu, m_pCtype, m_cname); if ( m_status != 0 ) { CPXgeterrorstring(m_env, m_status, m_error ); return 0; } m_status = CPXchgcoeflist(m_env, m_lp, m_nCoefItems, m_pRowNdx, m_pColNdx, m_pCoef); if ( m_status != 0 ) { CPXgeterrorstring(m_env, m_status, m_error ); return 0; } FreeMemory(); return m_lp; }
Solution cplex_init(TSP tsp, CPLEX cplex) { int n = tsp.n; int cols = tsp.cols; double *dists = tsp.distances; int *visits = malloc(sizeof(int) * n * n - n); double *rmatval = malloc(sizeof(double) * n * n - n); char **headers = malloc(sizeof(char *) * cols); double *lb = malloc(sizeof(double) * cols); double *ub = malloc(sizeof(double) * cols); char *ctype = malloc(sizeof(char) * cols); char **contraints = malloc(sizeof(char *) * n); double *rhs = malloc(sizeof(double) * n); char *senses = malloc(sizeof(char) * n); int *rmatbeg = malloc(sizeof(int) * n); char str[16]; for (int i = 0; i < n; ++i) { sprintf(str, "visit(%d)", i+1); contraints[i] = strdup(str); rhs[i] = 2; senses[i] = 'E'; rmatbeg[i] = i * (n-1); } for (int pos = 0; pos < cols; ++pos) { Pair pair = tsp.pairs[pos]; int first = (pair.i.id * (n-1)) + (pair.j.id-1); int second = (pair.j.id * (n-1)) + pair.i.id; visits[first] = visits[second] = pos; rmatval[first] = rmatval[second] = 1; sprintf(str, "x(%d,%d)", pair.i.num, pair.j.num); headers[pos] = strdup(str); lb[pos] = 0; ub[pos] = 1; ctype[pos] = CPX_BINARY; // set the var to binary (value of 1 or 0) } CPXnewcols(cplex.env, cplex.lp, cols, dists, lb, ub, ctype, headers); CPXaddrows(cplex.env, cplex.lp, 0, n, n*n-n, rhs, senses, rmatbeg, visits, rmatval, NULL, contraints); Solution solution; solution.i = 0; solution.n = -1; return solution; }
static int populatebyrow (CPXENVptr env, CPXLPptr lp) { int status = 0; double obj[NUMCOLS]; double lb[NUMCOLS]; double ub[NUMCOLS]; char *colname[NUMCOLS]; int rmatbeg[NUMROWS]; int rmatind[NUMNZ]; double rmatval[NUMNZ]; double rhs[NUMROWS]; char sense[NUMROWS]; char *rowname[NUMROWS]; status = CPXchgobjsen (env, lp, CPX_MAX); /* Problem is maximization */ if ( status ) goto TERMINATE; /* Now create the new columns. First, populate the arrays. */ obj[0] = 1.0; obj[1] = 2.0; obj[2] = 3.0; lb[0] = 0.0; lb[1] = 0.0; lb[2] = 0.0; ub[0] = 40.0; ub[1] = CPX_INFBOUND; ub[2] = CPX_INFBOUND; colname[0] = "x1"; colname[1] = "x2"; colname[2] = "x3"; status = CPXnewcols (env, lp, NUMCOLS, obj, lb, ub, NULL, colname); if ( status ) goto TERMINATE; /* Now add the constraints. */ rmatbeg[0] = 0; rowname[0] = "c1"; rmatind[0] = 0; rmatind[1] = 1; rmatind[2] = 2; sense[0] = 'L'; rmatval[0] = -1.0; rmatval[1] = 1.0; rmatval[2] = 1.0; rhs[0] = 20.0; rmatbeg[1] = 3; rowname[1] = "c2"; rmatind[3] = 0; rmatind[4] = 1; rmatind[5] = 2; sense[1] = 'L'; rmatval[3] = 1.0; rmatval[4] = -3.0; rmatval[5] = 1.0; rhs[1] = 30.0; status = CPXaddrows (env, lp, 0, NUMROWS, NUMNZ, rhs, sense, rmatbeg, rmatind, rmatval, NULL, rowname); if ( status ) goto TERMINATE; TERMINATE: return (status); } /* END populatebyrow */
static int populatebyrow (CPXENVptr env, CPXLPptr lp, int nfoods, double *cost, double *lb, double *ub, int nnutr, double *nutrmin, double *nutrmax, double **nutrper) { int status = 0; int zero = 0; int *ind = NULL; int i, j; ind = (int*) malloc(nfoods * sizeof(int)); if ( ind == NULL ) { status = CPXERR_NO_MEMORY; goto TERMINATE; } for (j = 0; j < nfoods; j++) { ind[j] = j; } status = CPXnewcols (env, lp, nfoods, cost, lb, ub, NULL, NULL); if ( status ) goto TERMINATE; for (i = 0; i < nnutr; i++) { double rng = nutrmax[i] - nutrmin[i]; status = CPXaddrows (env, lp, 0, 1, nfoods, nutrmin+i, "R", &zero, ind, nutrper[i], NULL, NULL); if ( status ) goto TERMINATE; status = CPXchgrngval (env, lp, 1, &i, &rng); if ( status ) goto TERMINATE; } TERMINATE: free_and_null ((char **)&ind); return (status); } /* END populatebyrow */
// ends up objective function construction int cplex_solver::end_objectives(void) { if (objectives.size() > 0) { int status = 0, nb_coeffs = 0; // Set the first objective as the actual objective for (int k = 0; k < nb_vars; k++) coefficients[k] = 0; for (; first_objective < (int)objectives.size(); first_objective++) if ((nb_coeffs = objectives[first_objective]->nb_coeffs) > 0) break; if (nb_coeffs > 0) for (int k = 0; k < nb_coeffs; k++) coefficients[objectives[first_objective]->sindex[k]] = objectives[first_objective]->coefficients[k]; else if (first_objective == (int)objectives.size()) first_objective--; // So that we solve at least one pbs status = CPXnewcols (env, lp, nb_vars, coefficients, lb, ub, vartype, varname); if (status) { fprintf(stderr, "cplex_solver: end_objective: cannot create objective function.\n"); exit(-1); } } return 0; }
int main(int argc, char *argv[]) { if(argc < 3){ cerr << "Uso: input_file max_iteraciones" << endl; exit(1); } srand(time(NULL)); string archivo_entrada(argv[1]); int max_iteraciones = atoi(argv[2]); //----------------------- PARSEO DE ENTRADA pair <int, pair<vector<vector<bool> >*, vector<vector<bool> >* > > grafo = parsear_entrada(archivo_entrada); int cant_ejes = grafo.first; vector<vector<bool> > *adyacencias = grafo.second.first; // matriz de adyacencia vector<vector<bool> > *particion = grafo.second.second; // filas: subconjuntos de la particion. columnas: nodos. // Variables binarias: // * X_n_j = nodo n pintado con el color j? (son cant_nodos * cant_colores_disp variables) // * W_j = hay algun nodo pintado con el color j? (son cant_colores_disp variables) // => TOTAL: (cant_nodos * cant_colores_disp + cant_colores_disp) variables // // Orden de las variables: // X_0_0, X_0_1, ... , X_0_(cant_col_disp), X_1_0, ... , X_(cant_nodos)_(cant_col_disp), W_0, ... , W(cant_col_disp) int cant_nodos = adyacencias->size(); int cant_subconj_particion = particion->size(); //cant de subconjuntos de la particion int cant_colores_disp = particion->size(); // cant colores usados <= cant de subconjuntos de la particion int n = cant_nodos * cant_colores_disp + cant_colores_disp; // n = cant de variables //----------------------- CARGA DE LP // Genero el problema de cplex. int status; CPXENVptr env; // Puntero al entorno. CPXLPptr lp; // Puntero al LP // Creo el entorno. env = CPXopenCPLEX(&status); if (env == NULL) { cerr << "Error creando el entorno" << endl; exit(1); } // Creo el LP. lp = CPXcreateprob(env, &status, "Coloreo Particionado"); if (lp == NULL) { cerr << "Error creando el LP" << endl; exit(1); } //TUNNING //Para que haga Branch & Cut: CPXsetintparam(env, CPX_PARAM_MIPSEARCH, CPX_MIPSEARCH_TRADITIONAL); //Para que no se adicionen planos de corte: ( => Branch & Bound) CPXsetintparam(env,CPX_PARAM_EACHCUTLIM, 0); CPXsetintparam(env, CPX_PARAM_FRACCUTS, -1); //Para facilitar la comparación evitamos paralelismo: CPXsetintparam(env, CPX_PARAM_THREADS, 1); //Para desactivar preprocesamiento CPXsetintparam(env, CPX_PARAM_PRESLVND, -1); CPXsetintparam(env, CPX_PARAM_REPEATPRESOLVE, 0); CPXsetintparam(env, CPX_PARAM_RELAXPREIND, 0); CPXsetintparam(env, CPX_PARAM_REDUCE, 0); CPXsetintparam(env, CPX_PARAM_LANDPCUTS, -1); //Otros parámetros // Para desactivar la salida poner CPX_OFF. Para activar: CPX_ON. status = CPXsetintparam(env, CPX_PARAM_SCRIND, CPX_OFF); if (status) { cerr << "Problema seteando SCRIND" << endl; exit(1); } //Setea el tiempo limite de ejecucion. status = CPXsetdblparam(env, CPX_PARAM_TILIM, 3600); if (status) { cerr << "Problema seteando el tiempo limite" << endl; exit(1); } double *ub, *lb, *objfun; // Cota superior, cota inferior, coeficiente de la funcion objetivo. char *xctype, **colnames; // tipo de la variable (por ahora son siempre continuas), string con el nombre de la variable. ub = new double[n]; lb = new double[n]; objfun = new double[n]; xctype = new char[n]; colnames = new char*[n]; // Defino las variables X_n_j for (int i = 0; i < n - cant_colores_disp; i++) { ub[i] = 1; lb[i] = 0; objfun[i] = 0; // Estas var no figuran en la funcion objetivo xctype[i] = 'C'; colnames[i] = new char[10]; sprintf(colnames[i], "X_%d_%d", i / cant_colores_disp, i % cant_colores_disp); } // Defino las variables W_j for (int i = n - cant_colores_disp; i < n; i++) { ub[i] = 1; lb[i] = 0; objfun[i] = 1; xctype[i] = 'C'; colnames[i] = new char[10]; sprintf(colnames[i], "W_%d", i - (n - cant_colores_disp)); } // Agrego las columnas. status = CPXnewcols(env, lp, n, objfun, lb, ub, NULL, colnames); if (status) { cerr << "Problema agregando las variables CPXnewcols" << endl; exit(1); } // Libero las estructuras. for (int i = 0; i < n; i++) { delete[] colnames[i]; } delete[] ub; delete[] lb; delete[] objfun; delete[] xctype; delete[] colnames; // Restricciones: // (1) Nodos adyacentes tienen distinto color (cant_ejes * cant_colores_disp restricciones por <=) // (2) Cada nodo tiene a lo sumo un color (cant_nodos restricciones por <=) // (3) Solo un nodo de cada subconj. de la particion tiene color (cant. de subconj. de la particion restricciones por =) // (4) W_j = 1 sii "X_i_j = 1 para algún i" (cant_colores_disp restricciones por >=) // (5) W_j >= W_(j+1) (cant_colores_disp - 1 restricciones por >=) // => TOTAL: (cant_ejes * cant_colores_disp + cant_nodos + cant_subconj_particion + cant_colores_disp + cant_colores_disp - 1) restricciones int ccnt = 0; //numero nuevo de columnas en las restricciones. int rcnt = cant_ejes * cant_colores_disp + cant_nodos + cant_subconj_particion + cant_colores_disp + cant_colores_disp - 1; //cuantas restricciones se estan agregando. int nzcnt = 0; //# de coeficientes != 0 a ser agregados a la matriz. Solo se pasan los valores que no son cero. char sense[rcnt]; // Sentido de la desigualdad. 'G' es mayor o igual y 'E' para igualdad. for(unsigned int i = 0; i < cant_ejes * cant_colores_disp; i++) sense[i] = 'L'; for(unsigned int i = cant_ejes * cant_colores_disp; i < cant_ejes * cant_colores_disp + cant_nodos; i++) sense[i] = 'L'; for(unsigned int i = cant_ejes * cant_colores_disp + cant_nodos; i < cant_ejes * cant_colores_disp + cant_nodos + cant_subconj_particion; i++) sense[i] = 'E'; for(unsigned int i = cant_ejes * cant_colores_disp + cant_nodos + cant_subconj_particion; i < rcnt; i++) sense[i] = 'G'; double *rhs = new double[rcnt]; // Termino independiente de las restricciones. int *matbeg = new int[rcnt]; //Posicion en la que comienza cada restriccion en matind y matval. int *matind = new int[rcnt*n]; // Array con los indices de las variables con coeficientes != 0 en la desigualdad. double *matval = new double[rcnt*n]; // Array que en la posicion i tiene coeficiente ( != 0) de la variable cutind[i] en la restriccion. //El termino indep. de restr (1), (2) y (3) es 1 for(unsigned int i = 0; i < cant_ejes * cant_colores_disp + cant_nodos + cant_subconj_particion; i++) rhs[i] = 1; //El termino indep. de restr (4) y (5) es 0 for(unsigned int i = cant_ejes * cant_colores_disp + cant_nodos + cant_subconj_particion; i < rcnt; i++) rhs[i] = 0; unsigned int indice = 0; //numero de restriccion actual //Restricciones (1) for(unsigned int i = 0; i < cant_nodos; i++) //itero nodo 1 for(unsigned int j = i+1; j < cant_nodos; j++) //itero nodo 2 if((*adyacencias)[i][j]) for(unsigned int p = 0; p < cant_colores_disp; p++){ //itero color matbeg[indice] = nzcnt; indice++; //cargo una de las variables participantes de la restr. matind[nzcnt] = cant_colores_disp*i + p; //var1: X_nodo1_color matval[nzcnt] = 1; nzcnt++; //idem con la otra variable matind[nzcnt] = cant_colores_disp*j + p; //var2: X_nodo2_color matval[nzcnt] = 1; nzcnt++; } //Restricciones (2) for(unsigned int i = 0; i < cant_nodos; i++){ //itero nodo matbeg[indice] = nzcnt; indice++; for(unsigned int p = 0; p < cant_colores_disp; p++){ //itero color matind[nzcnt] = cant_colores_disp*i + p; //var: X_nodo_color matval[nzcnt] = 1; nzcnt++; } } //Restricciones (3) for(unsigned int v = 0; v < cant_subconj_particion; v++){ //itero subconjunto de la particion matbeg[indice] = nzcnt; indice++; for(unsigned int i = 0; i < cant_nodos; i++) //itero nodo if((*particion)[v][i]) for(unsigned int p = 0; p < cant_colores_disp; p++){ //itero color matind[nzcnt] = cant_colores_disp*i + p; //var: X_nodo_color matval[nzcnt] = 1; nzcnt++; } } //Restricciones (4) for(unsigned int p = 0; p < cant_colores_disp; p++){ //itero color matbeg[indice] = nzcnt; indice++; matind[nzcnt] = cant_nodos * cant_colores_disp + p; //var: W_color matval[nzcnt] = cant_nodos; nzcnt++; for(unsigned int i = 0; i < cant_nodos; i++){ //itero nodo matind[nzcnt] = cant_colores_disp*i + p; //var: X_nodo_color matval[nzcnt] = -1; nzcnt++; } } //Restricciones (5) for(unsigned int p = 0; p < cant_colores_disp - 1; p++){ //itero color matbeg[indice] = nzcnt; indice++; matind[nzcnt] = cant_nodos * cant_colores_disp + p; //var: W_color matval[nzcnt] = 1; nzcnt++; matind[nzcnt] = cant_nodos * cant_colores_disp + p + 1; //var: W_(color+1) matval[nzcnt] = -1; nzcnt++; } // Esta rutina agrega la restriccion al lp. status = CPXaddrows(env, lp, ccnt, rcnt, nzcnt, rhs, sense, matbeg, matind, matval, NULL, NULL); if (status) { cerr << "Problema agregando restricciones." << endl; exit(1); } delete[] rhs; delete[] matbeg; delete[] matind; delete[] matval; // Escribimos el problema a un archivo .lp status = CPXwriteprob(env, lp, "output.lp", NULL); if (status) { cerr << "Problema escribiendo modelo" << endl; exit(1); } //----------------------- PRIMER ITERACION DE RESOLUCIÓN DEL LP // Tomamos el tiempo de resolucion utilizando CPXgettime. double inittime, endtime, fractpart, intpart, opt_anterior, opt_actual; int cant_iteraciones = 0; status = CPXgettime(env, &inittime); bool criterio_de_corte, todas_enteras, hubo_plano = true; status = CPXlpopt(env, lp); if (status) { cerr << "Problema optimizando CPLEX" << endl; exit(1); } status = CPXgetobjval(env, lp, &opt_actual); if (status) { cerr << "Problema obteniendo valor de mejor solucion." << endl; exit(1); } cout << "Optimo Inicial: " << opt_actual << endl << endl; double *sol = new double[n]; status = CPXgetx(env, lp, sol, 0, n - 1); if (status) { cerr << "Problema obteniendo la solucion del LP." << endl; exit(1); } // Chequeo si la solución es entera for (int i = 0; i < n; i++){ fractpart = modf(sol[i] , &intpart); if (fractpart > TOL){ todas_enteras = false; break; } } criterio_de_corte = todas_enteras || max_iteraciones==0; //----------------------- INICIO CICLO DE RESOLUCIÓN DEL LP while(!criterio_de_corte){ opt_anterior = opt_actual; hubo_plano = agregar_restricciones_clique(adyacencias, sol, env, lp, cant_colores_disp, n); hubo_plano = agregar_restricciones_ciclos(adyacencias, sol, env, lp, cant_colores_disp, n) || hubo_plano; if(hubo_plano){ status = CPXlpopt(env, lp); if (status) { cerr << "Problema optimizando CPLEX" << endl; exit(1); } status = CPXgetx(env, lp, sol, 0, n - 1); if (status) { cerr << "Problema obteniendo la solucion del LP." << endl; exit(1); } for (int i = 0; i < n; i++){ fractpart = modf(sol[i] , &intpart); if (fractpart > TOL){ todas_enteras = false; break; } } } status = CPXgetobjval(env, lp, &opt_actual); if (status) { cerr << "Problema obteniendo valor de mejor solucion." << endl; exit(1); } cant_iteraciones++; criterio_de_corte = todas_enteras || (cant_iteraciones >= max_iteraciones) || !hubo_plano;// || abs(opt_actual - opt_anterior) < TOL; } status = CPXgettime(env, &endtime); //----------------------- FIN CICLO DE RESOLUCIÓN DEL LP int solstat; char statstring[510]; CPXCHARptr p; solstat = CPXgetstat(env, lp); p = CPXgetstatstring(env, solstat, statstring); string statstr(statstring); cout << endl << "Resultado de la optimizacion: " << statstring << endl; if(solstat!=CPX_STAT_OPTIMAL) exit(1); double objval; status = CPXgetobjval(env, lp, &objval); if (status) { cerr << "Problema obteniendo valor de mejor solucion." << endl; exit(1); } cout << "Optimo: " << objval << "\t(Time: " << (endtime - inittime) << " sec)" << endl; // Tomamos los valores de la solucion y los escribimos a un archivo. std::string outputfile = "output.sol"; ofstream solfile(outputfile.c_str()); // Tomamos los valores de todas las variables. Estan numeradas de 0 a n-1. status = CPXgetx(env, lp, sol, 0, n - 1); if (status) { cerr << "Problema obteniendo la solucion del LP." << endl; exit(1); } // Solo escribimos las variables distintas de cero (tolerancia, 1E-05). solfile << "Status de la solucion: " << statstr << endl; // Imprimo var X_n_j for (int i = 0; i < n - cant_colores_disp; i++) { if (sol[i] > TOL) { solfile << "X_" << i / cant_colores_disp << "_" << i % cant_colores_disp << " = " << sol[i] << endl; } } // Imprimo var W_j for (int i = n - cant_colores_disp; i < n; i++) { if (sol[i] > TOL) { solfile << "W_" << i - (n - cant_colores_disp) << " = " << sol[i] << endl; } } solfile.close(); delete [] sol; delete adyacencias; delete particion; return 0; }
int CPLEXLoadVariables(MFAVariable* InVariable, bool RelaxIntegerVariables,bool UseTightBounds) { int Status = 0; //First I check the number of columns. If it's larger than the index, then this variable already exists and is only being changed int NumberColumns = CPXgetnumcols (CPLEXenv, CPLEXModel); if (NumberColumns <= InVariable->Index) { string StrName = GetMFAVariableName(InVariable); double* LB = new double; LB[0] = InVariable->LowerBound; double* UB = new double; UB[0] = InVariable->UpperBound; if (UseTightBounds) { LB[0] = InVariable->Min; UB[0] = InVariable->Max; } double* Obj = new double; Obj[0] = 0; char* Temp = new char; char** Name = new char*; Name[0] = new char[StrName.length()+1]; strcpy(Name[0],StrName.data()); if (InVariable->Binary && !RelaxIntegerVariables) { Temp[0] = CPX_BINARY; Status = CPXnewcols (CPLEXenv, CPLEXModel, 1, Obj, LB, UB, Temp, Name); } else if (InVariable->Integer && !RelaxIntegerVariables) { Temp[0] = CPX_INTEGER; Status = CPXnewcols (CPLEXenv, CPLEXModel, 1, Obj, LB, UB, Temp, Name); } else { Temp[0] = CPX_CONTINUOUS; Status = CPXnewcols (CPLEXenv, CPLEXModel, 1, Obj, LB, UB, Temp, Name); } delete LB; delete UB; delete Obj; delete Temp; delete [] Name[0]; delete Name; if (Status ) { FErrorFile() << "Could not add variable " << InVariable->Index << endl; FlushErrorFile(); return FAIL; } } else { double* Bounds = new double[2]; Bounds[0] = InVariable->LowerBound; Bounds[1] = InVariable->UpperBound; int* Indices = new int[2]; Indices[0] = InVariable->Index; Indices[1] = InVariable->Index; Status = CPXchgbds (CPLEXenv, CPLEXModel, 2, Indices, "LU", Bounds); delete [] Bounds; delete [] Indices; if (Status) { FErrorFile() << "Could not change bounds on variable " << InVariable->Index << endl; FlushErrorFile(); return FAIL; } } return SUCCESS; }
int main(int argc, char **argv) { int status = 0; CPXENVptr env = NULL; CPXLPptr lp = NULL; double obj[NUMCOLS]; double lb[NUMCOLS]; double ub[NUMCOLS]; double x[NUMCOLS]; int rmatbeg[NUMROWS]; int rmatind[NUMNZ]; double rmatval[NUMNZ]; double rhs[NUMROWS]; char sense[NUMROWS]; char ctype[NUMCOLS]; int solstat; double objval; env = CPXopenCPLEX (&status); CPXsetintparam(env, CPX_PARAM_MIPCBREDLP, CPX_OFF); CPXsetintparam(env, CPX_PARAM_PRELINEAR, CPX_OFF); /* Turn on traditional search for use with control callbacks */ // status = CPXsetintparam (env, CPXPARAM_MIP_Strategy_Search, // CPX_MIPSEARCH_TRADITIONAL); lp = CPXcreateprob(env, &status, "lpex1"); //CPXchgprobtype(env, lp, CPXPROB_MILP); CPXchgobjsen (env, lp, CPX_MAX); status = CPXsetlazyconstraintcallbackfunc (env, callback, NULL); lb[0] = 0.0; ub[0] = 40.0; lb[1] = 0.0; ub[1] = CPX_INFBOUND; lb[2] = 0.0; ub[2] = CPX_INFBOUND; obj[0] = 1.0; obj[1] = 2.0; obj[2] = 3.0; status = CPXnewcols (env, lp, NUMCOLS, obj, lb, ub, NULL, NULL); rmatbeg[0] = 0; rmatind[0] = 0; rmatind[1] = 1; rmatind[2] = 2; rmatval[0] = -1.0; rmatval[1] = 1.0; rmatval[2] = 1.0; sense[0] = 'L'; rhs[0] = 20.0; rmatbeg[1] = 3; rmatind[3] = 0; rmatind[4] = 1; rmatind[5] = 2; rmatval[3] = 1.0; rmatval[4] = -3.0; rmatval[5] = 1.0; sense[1] = 'L'; rhs[1] = 30.0; ctype[0] = 'I'; ctype[1] = 'C'; ctype[2] = 'I'; // status = CPXaddusercuts (env, lp, cutcnt, cutnzcnt, cutrhs, // cutsense, cutbeg, cutind, cutval, NULL); //status = CPXaddusercuts(env, lp, NUMROWS, NUMNZ, rhs, sense, rmatbeg, rmatind, rmatval, NULL ); status = CPXaddrows (env, lp, 0, NUMROWS, NUMNZ, rhs, sense, rmatbeg, rmatind, rmatval, NULL, NULL); status = CPXcopyctype (env, lp, ctype); // cuts int cmatbeg[1] = {0}; int cmatind[3] = {0,1,2}; double cmatval[3] = {1,0,0}; char csense[1] = {'L'}; double crhs[1] = {20}; //CPXaddusercuts doesnt work for some f*****g reason //status = CPXaddlazyconstraints(env, lp, 1, 3, crhs, csense, cmatbeg, cmatind, cmatval, NULL ); if ( status ) { fprintf (stderr, "Some f*****g error, status = %d.\n", status); } status = CPXmipopt (env, lp); /* Write the output to the screen. */ // solstat = CPXgetstat (env, lp); // printf ("\nSolution status = %d\n", solstat); // status = CPXgetobjval (env, lp, &objval); // printf ("Solution value = %f\n\n", objval); status = CPXsolution (env, lp, &solstat, &objval, x, NULL, NULL, NULL); printf ("\nSolution status = %d\n", solstat); printf ("Solution value = %f\n", objval); printf ("Solution= [%f, %f, %f]\n\n", x[0], x[1], x[2]); printf("This is great stuff\n"); return 0; }
inline int populatebynonzero (CPXENVptr env, CPXLPptr lp, int m, int n, int timeout, sched_nodeinfo_t *node_array, solver_job_list_t *job_array) { int NUMCOLS = n * (2 * m + 2); int NUMROWS = n * 3 + m * 2 + m * n * 2; int NUMNZ = 2 * n * (4 * m + 1); int NZc = 0; /* nonzero counter */ int status = 0; double *obj = NULL; obj = (double*)malloc(NUMCOLS * sizeof(double)); double *lb = (double*)malloc(NUMCOLS * sizeof(double)); double *ub = (double*)malloc(NUMCOLS * sizeof(double)); double *rhs = (double*)malloc(NUMROWS * sizeof(double)); char *sense = (char*)malloc(NUMROWS * sizeof(char)); /* char **colname = (char**)malloc(NUMCOLS * sizeof(char*)); char **rowname = (char**)malloc(NUMROWS * sizeof(char[10])); char str[10]; */ int *rowlist = (int*)malloc(NUMNZ * sizeof(int)); int *collist = (int*)malloc(NUMNZ * sizeof(int)); double *vallist = (double*)malloc(NUMNZ * sizeof(double)); int i, j, d; /*int rc = 0, cc = 0;*/ CPXchgobjsen (env, lp, CPX_MAX); /* Problem is maximization */ /* row definitions */ for (j = 0; j < n; j++) { sense[j] = 'E'; rhs[j] = 0.0; /*debug3("cpueq row counter: %d, no: %d",rc++, j);*/ /*sprintf(str,"CPUeq_%d",j+1); rowname[j] = str;*/ } for (i = 0; i < m; i++) { sense[n + i] = 'L'; rhs[n + i] = (double)(node_array[i].rem_cpus); /*sprintf(str,"NODEeq_%d",i+1); rowname[n + i] = str;*/ /*debug3("nodeeq row counter: %d, no: %d",rc++, n+i);*/ sense[n + m + i] = 'L'; rhs[n + m + i] = (double)(node_array[i].rem_gpus); /*debug3("gpueq row counter: %d, no: %d",rc++, n+m+i);*/ /*sprintf(str,"GPUeq_%d",i+1); rowname[n + m + i] = str;*/ } for (j = 0; j < n; j++) { for (i = 0; i < m; i++) { d = n + 2 * m + j * m * 2 + i * 2; sense[d] = 'L'; rhs[d] = 0.0; /*debug3("t_i_j_le row counter: %d, no: %d",rc++,d);*/ /*sprintf(rowname[d],"t_%d_%d_LE",j+1,i+1); rowname[d] = str;*/ sense[d + 1] = 'G'; rhs[d + 1] = 0.0; /*debug3("t_i_j_ge row counter: %d, no: %d",rc++,d+1);*/ /*sprintf(rowname[d+1],"t_%d_%d_GE",j+1,i+1); rowname[d+1] = str;*/ } } for (j = 0; j < n; j++) { sense[n + 2 * m + n * m * 2 + j * 2] = 'L'; rhs[n + 2 * m + n * m * 2 + j * 2] = 0.0; /*debug3("minmax row counter: %d, no: %d",rc++,n + 2 * m + n * m * 2 + j * 2);*/ sense[n + 2 * m + n * m * 2 + j * 2 + 1] = 'G'; rhs[n + 2 * m + n * m * 2 + j * 2 + 1] = 0.0; /*debug3("minmax row counter: %d, no: %d",rc++,n + 2 * m + n * m * 2 + j * 2 + 1);*/ /*sprintf(str,"minmax_%d",j+1); rowname[n + 4 * m + n * m * 2 + j] = str;*/ } status = CPXnewrows (env, lp, NUMROWS, rhs, sense, NULL, NULL); if ( status ) goto TERMINATE; /*debug3("ROWS: %d, column def starting",NUMROWS);*/ /* column definitions */ for (j = 0; j < n; j++) { /*sprintf(str, "s_%d",j+1); colname[j] = str;*/ lb[j] = 0.0; ub[j] = 1.0; /*debug3("s_j col counter: %d, no: %d",cc++,j);*/ } /*debug3("defined s_j");*/ for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { /*sprintf(str, "x_%d_%d",i+1,j+1); colname[(i + 1) * n + j] = str;*/ lb[(i + 1) * n + j] = 0.0; ub[(i + 1) * n + j] = CPX_INFBOUND; /*debug3("x_i_j col counter: %d, no: %d",cc++,(i+1)*n+j);*/ } } /*debug3("defined x_i_j");*/ for (j = 0; j < n; j++) { /*sprintf(str, "c_%d",j+1); colname[n * (m + 1) + j] = str;*/ /* min_nodes_j <= c_j <= max_nodes_j */ lb[n * (m + 1) + j] = (m + 1) * (job_array[j].min_nodes); ub[n * (m + 1) + j] = (m + 1) * (job_array[j].max_nodes); /*debug3("c_j col counter: %d, no: %d",cc++,n*(m+1)+j);*/ } /*debug3("defined c_j");*/ for (j = 0; j < n; j++) { for (i = 0; i < m; i++) { /*sprintf(str, "t_%d_%d",j+1,i+1); colname[n * (m + 2) + j * m + i] = str;*/ lb[n * (m + 2) + j * m + i] = 0.0; ub[n * (m + 2) + j * m + i] = 1.0; /*debug3("t_i_j col counter: %d, no: %d",cc++,n*(m+2)+j*m+i);*/ } } /*debug3("defined t_i_j");*/ for (j = 0; j < NUMCOLS; j++) { obj[j] = 0; } for (j = 0; j < n; j++) { obj[j] = (job_array[j].priority); obj[n * (m + 1) + j] = (-1.0)*(job_array[j].priority); } status = CPXnewcols (env, lp, NUMCOLS, obj, lb, ub, NULL, NULL); if ( status ) goto TERMINATE; /*debug3("constraint coefficients");*/ /* constraints */ /* sum over nodes should be equal to job's required cpu */ /* sum_i(x_ij) = r_j * s_j */ for (j = 0; j < n; j++) { for (i = 0; i < m; i++) { rowlist[NZc] = j; vallist[NZc] = 1.0; collist[NZc++] = (i + 1) * n + j; /*debug3("con1 collist %d",(i + 1) * n + j);*/ } rowlist[NZc] = j; vallist[NZc] = (int)(-job_array[j].min_cpus); collist[NZc++] = j; /*debug3("con1 collist %d",j);*/ } /* nzc = m*n+n */ /* sum over jobs for cpu should be available on nodes */ /* sum_j(x_ij) <= R_i */ for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { /*debug3("con2 collist %d",(i + 1) * n + j);*/ rowlist[NZc] = n + i; vallist[NZc] = 1.0; collist[NZc++] = (i + 1) * n + j; } } /* nzc = 2*m*n+n */ /* sum over jobs for gpu should be available on nodes */ /* sum_j(t_ji * g_j) <= G_i */ for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { rowlist[NZc] = n + m + i; vallist[NZc] = job_array[j].gpu; collist[NZc++] = n * (m + 2) + j * m + i; /*debug3("con3 collist %d",n * (m + 2) + j * m + i);*/ } } /* nzc = 3*m*n+n */ status = CPXchgcoeflist (env, lp, NZc, rowlist, collist, vallist); if ( status ) goto TERMINATE; TERMINATE: free_and_null ((char **) &obj); free_and_null ((char **) &lb); free_and_null ((char **) &ub); free_and_null ((char **) &rhs); free_and_null ((char **) &sense); return (status); }
void PartitionedColoringModel::addVariables() { int status; double *upperBound, *lowerBound, *targetFunctionCoefficients; char *variableTypes, **variableNames; int amountOfNodes = this->graph->amountOfNodes(); this->amountOfVariables = (amountOfNodes * amountOfNodes) + amountOfNodes; upperBound = new double[this->amountOfVariables]; lowerBound = new double[this->amountOfVariables]; targetFunctionCoefficients = new double[this->amountOfVariables]; variableTypes = new char[this->amountOfVariables]; variableNames = new char*[this->amountOfVariables]; for(int variableNumber = 0; variableNumber < this->amountOfVariables; variableNumber++) { upperBound[variableNumber] = CPX_INFBOUND; lowerBound[variableNumber] = 0.0; if(this->variablePositionIsW(variableNumber)) { targetFunctionCoefficients[variableNumber] = 1.0; } else { targetFunctionCoefficients[variableNumber] = 0.0; } // Las seteo continuas, luego las convierto a integer cuando corresponda dependiendo del algoritmo variableTypes[variableNumber] = 'C'; variableNames[variableNumber] = new char[10]; if(this->variablePositionIsW(variableNumber)) { sprintf(variableNames[variableNumber], "w_%d", this->wModelIndexFromVariablePosition(variableNumber)); } else { int nodeNumber = this->xIModelIndexFromVariablePosition(variableNumber); int colorNumber = this->xJModelIndexFromVariablePosition(variableNumber); sprintf(variableNames[variableNumber], "x_%d_%d", nodeNumber, colorNumber); } } status = CPXnewcols(this->cplexEnvironment, this->linearProblem, this->amountOfVariables, targetFunctionCoefficients, lowerBound, upperBound, variableTypes, variableNames); if(status) { cerr << "Problema agregando las variables CPXnewcols" << endl; exit(1); } for(int i = 0; i < this->amountOfVariables; i++) { delete[] variableNames[i]; } delete[] upperBound; delete[] lowerBound; delete[] targetFunctionCoefficients; delete[] variableTypes; delete[] variableNames; }
void DDSIP_DetEqu () { CPXLPptr det_equ; int status, scen, i, j, k, nzcnt_row, ranged = 0; char probname[] = "sipout/det_equ.lp.gz"; double *scaled_obj_coef = NULL; char *sense = NULL, *sense_sorted = NULL; char **scen_spec_rowname = NULL; char **scen_spec_colname = NULL; char **rowname = NULL, *rownamestore = NULL; char **colname = NULL, *colnamestore = NULL; int rowstorespace, rowsurplus; int colstorespace, colsurplus; char *string1 = NULL, *string2 = NULL; double *lb = NULL, *lb_sorted = NULL; double *ub = NULL, *ub_sorted = NULL; double *rng = NULL, *rng_sorted = NULL; char *vartype = NULL, *vartype_sorted = NULL; int *colindex_sorted = NULL, *colindex_revers = NULL; double *value = NULL; double *det_equ_rhs = NULL; double *base_rhs = NULL; int nzcnt=0, *rmatbeg=NULL, *rmatind=NULL, *rmatbeg_stage=NULL, *rmatind_stage=NULL, *rowindex=NULL; double *rmatval=NULL, *rmatval_stage=NULL; double time_start, time_end; time_start = DDSIP_GetCpuTime (); k = abs(DDSIP_param->riskmod); if (k > 2 && k != 4) { fprintf (stderr, "\nNot building deterministic equivalent, not available for risk model %d\n",DDSIP_param->riskmod); fprintf (DDSIP_outfile, "\nNot building deterministic equivalent, not available for risk model %d\n",DDSIP_param->riskmod); return; } if (DDSIP_data->seccon) det_equ_rhs = (double *) DDSIP_Alloc(sizeof(double),DDSIP_Imax(DDSIP_Imax(DDSIP_data->seccon, DDSIP_param->scenarios), DDSIP_data->firstcon),"det_equ_rhs(DetEqu)"); else { fprintf (stderr,"XXX ERROR: no second stage contraints, got DDSIP_data->seccon=%d.\n",DDSIP_data->seccon); return; } fprintf (stderr, "\nBuilding deterministic equivalent.\nWorks only for expectation-based models.\n"); colstorespace = DDSIP_data->novar * 255; rowstorespace = DDSIP_data->nocon * 255; if (!(sense = (char *) DDSIP_Alloc (sizeof (char), DDSIP_data->nocon, "sense(DetEqu)")) || !(sense_sorted = (char *) DDSIP_Alloc (sizeof (char), DDSIP_Imax(DDSIP_param->scenarios, DDSIP_Imax(DDSIP_data->firstcon,DDSIP_data->seccon)), "sense_sorted(DetEqu)")) || !(base_rhs = (double *) DDSIP_Alloc(sizeof(double),DDSIP_data->nocon,"base_rhs(DetEqu)")) || !(scaled_obj_coef = (double *) DDSIP_Alloc (sizeof (double), DDSIP_Imax(DDSIP_data->firstvar, DDSIP_data->secvar), "base_rhs(DetEqu)")) || !(colname = (char **) DDSIP_Alloc (sizeof (char *), DDSIP_data->novar,"base_rhs(DetEqu)")) || !(scen_spec_colname = (char **) DDSIP_Alloc (sizeof (char *), DDSIP_Imax(DDSIP_data->firstvar,DDSIP_data->secvar), "scen_spec_colname(DetEqu)")) || !(colnamestore = (char *) DDSIP_Alloc (sizeof (char), colstorespace, "colnamestore(DetEqu)")) || !(rowname = (char **) DDSIP_Alloc (sizeof (char *), DDSIP_data->nocon, "rowname(DetrEqu)")) || !(scen_spec_rowname = (char **) DDSIP_Alloc (sizeof (char *), DDSIP_Imax(DDSIP_param->scenarios, DDSIP_Imax(DDSIP_data->firstcon,DDSIP_data->seccon)), "scen_spec_rowname(DetEqu)")) || !(rownamestore = (char *) DDSIP_Alloc (sizeof (char), rowstorespace, "rownamestore(DetEqu)")) || !(lb = (double *) DDSIP_Alloc (sizeof (double), DDSIP_data->novar, "lb(DetEqu)")) || !(lb_sorted = (double *) DDSIP_Alloc (sizeof (double), DDSIP_Imax(DDSIP_data->firstvar,DDSIP_data->secvar), "lb_sorted(DetEqu)")) || !(ub = (double *) DDSIP_Alloc (sizeof (double), DDSIP_data->novar, "ub(DetEqu)")) || !(ub_sorted = (double *) DDSIP_Alloc (sizeof (double), DDSIP_Imax(DDSIP_data->firstvar,DDSIP_data->secvar), "ub_sorted(DetEqu)")) || !(vartype = (char *) DDSIP_Alloc (sizeof (char), DDSIP_data->novar, "vartype(DetEqu)")) || !(vartype_sorted = (char *) DDSIP_Alloc (sizeof (double), DDSIP_Imax(DDSIP_data->firstvar,DDSIP_data->secvar), "vartype_sorted(DetEqu)")) || !(colindex_sorted = (int *) DDSIP_Alloc (sizeof (int), DDSIP_data->novar, "colindex_sorted(DetEqu)")) || !(rowindex = (int *) DDSIP_Alloc (sizeof (int), DDSIP_Imax(DDSIP_data->firstcon, DDSIP_data->seccon), "rowindex(DetEqu)"))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); goto FREE; } // get problem data /*____________________________________________________________________________________*/ if((status = CPXgetcolname (DDSIP_env, DDSIP_lp, colname, colnamestore, colstorespace, &colsurplus, 0, DDSIP_data->novar - 1)) || (status = CPXgetrowname (DDSIP_env, DDSIP_lp, rowname, rownamestore, rowstorespace, &rowsurplus, 0, DDSIP_data->nocon - 1)) || (status = CPXgetsense (DDSIP_env, DDSIP_lp, sense, 0, DDSIP_data->nocon - 1)) || (status = CPXgetrhs (DDSIP_env, DDSIP_lp, base_rhs, 0, DDSIP_data->nocon - 1)) || (status = CPXgetlb (DDSIP_env, DDSIP_lp, lb, 0, DDSIP_data->novar - 1)) || (status = CPXgetub (DDSIP_env, DDSIP_lp, ub, 0, DDSIP_data->novar - 1)) || (status = CPXgetctype (DDSIP_env, DDSIP_lp, vartype, 0, DDSIP_data->novar - 1))) { fprintf (stderr, "Coud not get problem data, returned %d\n", status); goto FREE; } // check whether there are ranged rows for (j=0; j<DDSIP_data->nocon; j++) { if (sense[j] == 'R') { ranged = 1; break; } } if (ranged) { if (!(rng = (double *) DDSIP_Alloc (sizeof (double), DDSIP_data->nocon, "rng(DetEqu)")) || !(rng_sorted = (double *) DDSIP_Alloc (sizeof (double), DDSIP_Imax(DDSIP_data->firstcon,DDSIP_data->seccon), "rng_sorted(DetEqu)"))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); goto FREE; } if ((status = CPXgetrngval (DDSIP_env, DDSIP_lp, rng, 0, DDSIP_data->nocon-1))) { fprintf (stderr, "Coud not get problem ranges, returned %d\n", status); goto FREE; } } /*____________________________________________________________________________________*/ // create empty problem det_equ = CPXcreateprob (DDSIP_env, &status, probname); if (status) { fprintf (stderr, "CPXcreateprob returned %d\n", status); goto FREE; } // add (original) first-stage variables for (j = 0; j < DDSIP_data->firstvar; j++) { vartype_sorted[j] = vartype[DDSIP_bb->firstindex[j]]; lb_sorted[j] = lb[DDSIP_bb->firstindex[j]]; ub_sorted[j] = ub[DDSIP_bb->firstindex[j]]; if (DDSIP_param->deteqType && DDSIP_param->riskmod >= 0) scaled_obj_coef[j] = DDSIP_data->obj_coef[DDSIP_bb->firstindex[j]]; scen_spec_colname[j]= colname[DDSIP_bb->firstindex[j]]; } if ((status = CPXnewcols (DDSIP_env, det_equ, DDSIP_data->firstvar, scaled_obj_coef, lb_sorted, ub_sorted, vartype_sorted, scen_spec_colname))) { fprintf (stderr, "CPXnewcols returned %d for first-stage variables\n", status); goto FREE; } // add (original) second-stage variables for all scenarios for (j = 0; j < DDSIP_data->secvar; j++) { vartype_sorted[j] = vartype[DDSIP_bb->secondindex[j]]; lb_sorted[j] = lb[DDSIP_bb->secondindex[j]]; ub_sorted[j] = ub[DDSIP_bb->secondindex[j]]; } for (scen = 0; scen < DDSIP_param->scenarios; scen++) { for (j = 0; j < DDSIP_data->secvar; j++) { if (!(string2 = (char *) calloc (1, 255 * sizeof (char)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); goto FREE; } // append scenario index to colname string1 = colname[DDSIP_bb->secondindex[j]]; sprintf (string2, "%sSC%.3d", string1, scen+1); scen_spec_colname[j] = string2; if (DDSIP_param->deteqType && DDSIP_param->riskmod >= 0) scaled_obj_coef[j] = DDSIP_data->prob[scen] * DDSIP_data->obj_coef[DDSIP_bb->secondindex[j]]; } if ((status = CPXnewcols (DDSIP_env, det_equ, DDSIP_data->secvar, scaled_obj_coef, lb_sorted, ub_sorted, vartype_sorted, scen_spec_colname))) { fprintf (stderr, "CPXnewcols returned %d for second-stage variables of scenario %d\n", status, scen+1); goto FREE; } for (j = 0; j < DDSIP_data->secvar; j++) DDSIP_Free ((void **) &(scen_spec_colname[j])); } // add second-stage variable for objective value of the scenarios if (!(string2 = (char *) calloc (1, 255 * sizeof (char)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); goto FREE; } scen_spec_colname[0] = string2; for (scen = 0; scen < DDSIP_param->scenarios; scen++) { vartype_sorted[0] = 'C'; lb_sorted[0] = -DDSIP_infty; ub_sorted[0] = DDSIP_infty; sprintf (string2, "DDSIPobj_SC%.3d", scen+1); if (!DDSIP_param->deteqType && DDSIP_param->riskmod >= 0) scaled_obj_coef[0] = DDSIP_data->prob[scen]; else scaled_obj_coef[0] = 0.; if ((status = CPXnewcols (DDSIP_env, det_equ, 1, scaled_obj_coef, lb_sorted, ub_sorted, vartype_sorted, scen_spec_colname))) { fprintf (stderr, "CPXnewcols returned %d for second-stage variable DDSIPobj_SC%.3d\n", status, scen+1); goto FREE; } } // add the additional variables needed for risk models /////////////////////////////////////// if (DDSIP_param->riskmod) { switch (abs(DDSIP_param->riskmod)) { case 1: // Expected excess // one continuous second-stage variable for each scenario for (scen = 0; scen < DDSIP_param->scenarios; scen++) { vartype_sorted[0] = 'C'; lb_sorted[0] = 0.; ub_sorted[0] = DDSIP_infty; sprintf (string2, "DDSIP_expexc_SC%.3d", scen+1); if (DDSIP_param->riskmod > 0) scaled_obj_coef[0] = DDSIP_param->riskweight*DDSIP_data->prob[scen]; else if (DDSIP_param->riskmod < 0) scaled_obj_coef[0] = DDSIP_data->prob[scen]; else scaled_obj_coef[0] = 0.; if ((status = CPXnewcols (DDSIP_env, det_equ, 1, scaled_obj_coef, lb_sorted, ub_sorted, vartype_sorted, scen_spec_colname))) { fprintf (stderr, "CPXnewcols returned %d for second-stage variable %s\n", status, string2); goto FREE; } } break; case 2: // Excess Probability // one binary second-stage variable for each scenario for (scen = 0; scen < DDSIP_param->scenarios; scen++) { vartype_sorted[0] = 'B'; lb_sorted[0] = 0.; ub_sorted[0] = 1.; sprintf (string2, "DDSIP_excprob_SC%.3d", scen+1); if (DDSIP_param->riskmod > 0) scaled_obj_coef[0] = DDSIP_param->riskweight*DDSIP_data->prob[scen]; else if (DDSIP_param->riskmod < 0) scaled_obj_coef[0] = DDSIP_data->prob[scen]; else scaled_obj_coef[0] = 0.; if ((status = CPXnewcols (DDSIP_env, det_equ, 1, scaled_obj_coef, lb_sorted, ub_sorted, vartype_sorted, scen_spec_colname))) { fprintf (stderr, "CPXnewcols returned %d for second-stage variable %s\n", status, string2); goto FREE; } } break; case 4: // Worst Case Costs // one continuous first-stage variable vartype_sorted[0] = 'C'; lb_sorted[0] = -DDSIP_infty; ub_sorted[0] = DDSIP_infty; if (DDSIP_param->prefix) { if (!(strlen(DDSIP_param->prefix))) { fprintf (stderr," *** ERROR: The prefix for the first stage variables has to have a positive length.\n"); exit (1); } sprintf (string2, "%sDDSIP_n_aux01",DDSIP_param->prefix); } else { if (!(strlen(DDSIP_param->postfix))) { fprintf (stderr," *** ERROR: The postfix for the first stage variables has to have a positive length.\n"); exit (1); } sprintf (string2, "DDSIP_worstc_%s",DDSIP_param->postfix); } if (DDSIP_param->riskmod > 0) scaled_obj_coef[0] = DDSIP_param->riskweight; else if (DDSIP_param->riskmod < 0) scaled_obj_coef[0] = 1.; else scaled_obj_coef[0] = 0.; if ((status = CPXnewcols (DDSIP_env, det_equ, 1, scaled_obj_coef, lb_sorted, ub_sorted, vartype_sorted, scen_spec_colname))) { fprintf (stderr, "CPXnewcols returned %d for second-stage variable %s\n", status, string2); goto FREE; } } } DDSIP_Free ((void **) &(scen_spec_colname[0])); ///////enter stochastic cost coefficients in case of deteqType 1 ////////////////////////////// if (DDSIP_param->stoccost && DDSIP_param->deteqType && DDSIP_param->riskmod >= 0) { for (j = 0; j < DDSIP_param->stoccost; j++) { scaled_obj_coef[j] = 0.0; if ((colindex_sorted[j] = DDSIP_bb->firstindex_reverse[DDSIP_data->costind[j]])) colindex_sorted[j] = DDSIP_data->firstvar + DDSIP_bb->secondindex_reverse[DDSIP_data->costind[j]]; } for (scen = 0; scen < DDSIP_param->scenarios; scen++) { for (j = 0; j < DDSIP_param->stoccost; j++) { if (colindex_sorted[j] >= DDSIP_data->firstvar) scaled_obj_coef[j] = DDSIP_data->prob[scen] * DDSIP_data->cost[scen * DDSIP_param->stoccost + j]; else scaled_obj_coef[j] += DDSIP_data->prob[scen] * DDSIP_data->cost[scen * DDSIP_param->stoccost + j]; } status = CPXchgobj (DDSIP_env, det_equ, DDSIP_param->stoccost, colindex_sorted, scaled_obj_coef); if (status) { char errmsg[1024]; CPXgeterrorstring (DDSIP_env, status, errmsg); fprintf (stderr, "in DetEqu: %s\n", errmsg); } for (j = 0; j < DDSIP_param->stoccost; j++) { if (colindex_sorted[j] >= DDSIP_data->firstvar) colindex_sorted[j] += DDSIP_data->secvar; } } } // // free arrays needeed only for columns DDSIP_Free ((void **) &(vartype)); DDSIP_Free ((void **) &(colname)); DDSIP_Free ((void **) &(colnamestore)); DDSIP_Free ((void **) &(lb)); DDSIP_Free ((void **) &(ub)); DDSIP_Free ((void **) &(vartype_sorted)); DDSIP_Free ((void **) &(lb_sorted)); DDSIP_Free ((void **) &(ub_sorted)); DDSIP_Free ((void **) &(scaled_obj_coef)); // // get problem matrix coefficients // query the length needed for storage of coefficients CPXgetrows(DDSIP_env, DDSIP_lp, &nzcnt, rmatbeg, rmatind, rmatval, 0, &rowsurplus, 0, DDSIP_data->nocon-1); nzcnt = -rowsurplus; if (!(rmatbeg = (int *) DDSIP_Alloc (sizeof (int), DDSIP_data->nocon, "rmatbeg(DetEqu)")) || !(rmatind = (int *) DDSIP_Alloc (sizeof (int), DDSIP_Imax(nzcnt, DDSIP_param->stocmat), "rmatind(DetEqu)")) || !(rmatval = (double *) DDSIP_Alloc (sizeof (double), nzcnt, "rmatval(DetEqu)"))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); goto FREE; } CPXgetrows(DDSIP_env, DDSIP_lp, &nzcnt, rmatbeg, rmatind, rmatval, nzcnt, &rowsurplus, 0, DDSIP_data->nocon-1); printf(" got %d elements of the matrix\n", nzcnt); k = DDSIP_Imax(nzcnt + DDSIP_param->stocmat, DDSIP_param->scenarios*(DDSIP_data->novar+1)); if (!(rmatbeg_stage = (int *) DDSIP_Alloc (sizeof (int), DDSIP_Imax(DDSIP_param->scenarios, DDSIP_Imax(DDSIP_data->firstcon, DDSIP_data->seccon)), "rmatbeg_stage(DetEqu)")) || !(rmatind_stage = (int *) DDSIP_Alloc (sizeof (int), k, "rmatind_stage(DetEqu)")) || !(rmatval_stage = (double *) DDSIP_Alloc (sizeof (double), k, "rmatval_stage(DetEqu)"))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); goto FREE; } // add first-stage constraints k = 0; for (j = 0; j < DDSIP_data->firstcon; j++) { sense_sorted[j] = sense[DDSIP_bb->firstrowind[j]]; det_equ_rhs[j] = base_rhs[DDSIP_bb->firstrowind[j]]; scen_spec_rowname[j] = rowname[DDSIP_bb->firstrowind[j]]; rmatbeg_stage[j] = k; if (DDSIP_bb->firstrowind[j] == DDSIP_data->nocon -1) nzcnt_row = nzcnt - rmatbeg[DDSIP_data->nocon -1]; else nzcnt_row = rmatbeg[DDSIP_bb->firstrowind[j]+1] - rmatbeg[DDSIP_bb->firstrowind[j]]; for (i = 0; i < nzcnt_row; i++) { rmatind_stage[k + i] = DDSIP_bb->firstindex_reverse[rmatind[rmatbeg[DDSIP_bb->firstrowind[j]] + i]]; rmatval_stage[k + i] = rmatval[rmatbeg[DDSIP_bb->firstrowind[j]] + i]; } k += nzcnt_row; } if ((status = CPXaddrows(DDSIP_env, det_equ, 0, DDSIP_data->firstcon, k, det_equ_rhs, sense_sorted, rmatbeg_stage, rmatind_stage, rmatval_stage, NULL, scen_spec_rowname))) { fprintf (stderr, "CPXaddrows returned %d for first-stage constraints\n", status); goto FREE; } if (ranged) { for (j = 0; j < DDSIP_data->firstcon; j++) { rng_sorted[j] = rng[DDSIP_bb->firstrowind[j]]; rowindex[j] = j; } if((status = CPXchgrngval(DDSIP_env, det_equ, DDSIP_data->firstcon, rowindex, rng_sorted))) { fprintf (stderr, "CPXchgrngval returned %d for first-stage constraints\n", status); goto FREE; } } // add second-stage constraints for (scen = 0; scen < DDSIP_param->scenarios; scen++) { k = 0; for (j = 0; j < DDSIP_data->seccon; j++) { sense_sorted[j] = sense[DDSIP_bb->secondrowind[j]]; det_equ_rhs[j] = base_rhs[DDSIP_bb->secondrowind[j]]; if (!(string2 = (char *) calloc (1, 255 * sizeof (char)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); goto FREE; } // append scenario index to colname string1 = rowname[DDSIP_bb->secondrowind[j]]; sprintf (string2, "%sSC%.3d", string1, scen+1); scen_spec_rowname[j] = string2; rmatbeg_stage[j] = k; if (DDSIP_bb->secondrowind[j] == DDSIP_data->nocon -1) nzcnt_row = nzcnt - rmatbeg[DDSIP_data->nocon -1]; else { nzcnt_row = rmatbeg[DDSIP_bb->secondrowind[j]+1] - rmatbeg[DDSIP_bb->secondrowind[j]]; } for (i = 0; i < nzcnt_row; i++) { if (DDSIP_bb->firstindex_reverse[rmatind[rmatbeg[DDSIP_bb->secondrowind[j]] + i]] < 0) rmatind_stage[k + i] = DDSIP_data->firstvar + scen*DDSIP_data->secvar + DDSIP_bb->secondindex_reverse[rmatind[rmatbeg[DDSIP_bb->secondrowind[j]] + i]]; else rmatind_stage[k + i] = DDSIP_bb->firstindex_reverse[rmatind[rmatbeg[DDSIP_bb->secondrowind[j]] + i]]; rmatval_stage[k + i] = rmatval[rmatbeg[DDSIP_bb->secondrowind[j]] + i]; } k += nzcnt_row; } ///////enter stochastic rhs entries////////////////////////////////////////////////////// for (j=0; j< DDSIP_param->stocrhs; j++) { det_equ_rhs[DDSIP_bb->secondrowind_reverse[DDSIP_data->rhsind[j]]] = DDSIP_data->rhs[scen * DDSIP_param->stocrhs + j]; } if ((status = CPXaddrows(DDSIP_env, det_equ, 0, DDSIP_data->seccon, k, det_equ_rhs, sense_sorted, rmatbeg_stage, rmatind_stage, rmatval_stage, NULL, scen_spec_rowname))) { fprintf (stderr, "CPXaddrows returned %d for second-stage constraints scenario %d\n", status, scen+1); goto FREE; } for (j = 0; j < DDSIP_data->seccon; j++) DDSIP_Free ((void **) &(scen_spec_rowname[j])); if (ranged) { for (j = 0; j < DDSIP_data->seccon; j++) { rng_sorted[j] = rng[DDSIP_bb->secondrowind[j]]; rowindex[j] = DDSIP_data->firstcon + scen * DDSIP_data->seccon + j; } if ((status = CPXchgrngval(DDSIP_env, det_equ, DDSIP_data->seccon, rowindex, rng_sorted))) { fprintf (stderr, "CPXchgrngval returned %d for first-stage constraints\n", status); goto FREE; } } } ///////enter stochastic matrix entries////////////////////////////////////////////////////// if (DDSIP_param->stocmat) { if (!(value = (double *) calloc (DDSIP_param->stocmat, sizeof (double)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); goto FREE; } for (j = 0; j < DDSIP_param->stocmat; j++) { if ((colindex_sorted[j] = DDSIP_bb->firstindex_reverse[DDSIP_data->matcol[j]])) colindex_sorted[j] = DDSIP_data->firstvar + DDSIP_bb->secondindex_reverse[DDSIP_data->matcol[j]]; rmatind[j] = DDSIP_data->firstcon + DDSIP_bb->secondrowind_reverse[DDSIP_data->matrow[j]]; } for (scen = 0; scen < DDSIP_param->scenarios; scen++) { for (j = 0; j < DDSIP_param->stocmat; j++) { value[j] = DDSIP_data->matval[scen * DDSIP_param->stocmat + j]; } status = CPXchgcoeflist (DDSIP_env, det_equ, DDSIP_param->stocmat, rmatind, colindex_sorted, value); if (status) { char errmsg[1024]; CPXgeterrorstring (DDSIP_env, status, errmsg); fprintf (stderr, "in DetEqu chgcoeflist returned %d: %s\n", status, errmsg); } for (j = 0; j < DDSIP_param->stocmat; j++) { rmatind[j] += DDSIP_data->seccon; if (colindex_sorted[j] >= DDSIP_data->firstvar) colindex_sorted[j] += DDSIP_data->secvar; } } DDSIP_Free ((void **) &(value)); } // add second-stage equations for the objective values of the scenarios k = 0; for (scen = 0; scen < DDSIP_param->scenarios; scen++) { sense_sorted[scen] = 'E'; det_equ_rhs[scen] = 0.; if (!(string2 = (char *) calloc (1, 255 * sizeof (char)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); goto FREE; } sprintf (string2, "DDSIP_o_SC%.3d", scen+1); scen_spec_rowname[scen] = string2; rmatbeg_stage[scen] = k; nzcnt_row = DDSIP_data->novar + 1; for (i = 0; i < DDSIP_data->novar; i++) { if (DDSIP_bb->firstindex_reverse[i] < 0) { rmatind_stage[k + i] = DDSIP_data->firstvar + scen*DDSIP_data->secvar + DDSIP_bb->secondindex_reverse[i]; } else { rmatind_stage[k + i] = DDSIP_bb->firstindex_reverse[i]; } rmatval_stage[k + i] = DDSIP_data->obj_coef[i]; } rmatind_stage[k + DDSIP_data->novar] = DDSIP_data->firstvar + DDSIP_param->scenarios*DDSIP_data->secvar + scen; rmatval_stage[k + DDSIP_data->novar] = -1.; k += nzcnt_row; } if ((status = CPXaddrows(DDSIP_env, det_equ, 0, DDSIP_param->scenarios, k, det_equ_rhs, sense_sorted, rmatbeg_stage, rmatind_stage, rmatval_stage, NULL, scen_spec_rowname))) { fprintf (stderr, "CPXaddrows returned %d for second-stage objective constraints\n", status); goto FREE; } for (scen = 0; scen < DDSIP_param->scenarios; scen++) { DDSIP_Free ((void **) &(scen_spec_rowname[scen])); } ///////enter stochastic cost coefficients in the objective equations ////////////////////////////// if (DDSIP_param->stoccost) { if (!(value = (double *) calloc (DDSIP_param->stoccost, sizeof (double)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); goto FREE; } for (scen = 0; scen < DDSIP_param->scenarios; scen++) { for (j = 0; j < DDSIP_param->stoccost; j++) { if ((colindex_sorted[j] = DDSIP_bb->firstindex_reverse[DDSIP_data->costind[j]]) < 0) colindex_sorted[j] = DDSIP_data->firstvar + scen * DDSIP_data->secvar +DDSIP_bb->secondindex_reverse[DDSIP_data->costind[j]]; rmatind[j] = DDSIP_data->firstcon + DDSIP_param->scenarios*DDSIP_data->seccon + scen; value[j] = DDSIP_data->cost[scen * DDSIP_param->stoccost + j]; } status = CPXchgcoeflist (DDSIP_env, det_equ, DDSIP_param->stoccost, rmatind, colindex_sorted, value); if (status) { char errmsg[1024]; CPXgeterrorstring (DDSIP_env, status, errmsg); fprintf (stderr, "in DetEqu chgcoeflist returned %d: %s\n", status, errmsg); } for (j = 0; j < DDSIP_param->stocmat; j++) { rmatind[j] += DDSIP_data->seccon; if (colindex_sorted[j] >= DDSIP_data->firstvar) colindex_sorted[j] += DDSIP_data->secvar; } } DDSIP_Free ((void **) &(value)); } // add second-stage equations for the risk models ////////////////////////////////// switch (abs(DDSIP_param->riskmod)) { case 1: // Expected excess k = 0; for (scen = 0; scen < DDSIP_param->scenarios; scen++) { sense_sorted[scen] = 'L'; det_equ_rhs[scen] = DDSIP_param->risktarget; if (!(string2 = (char *) calloc (1, 255 * sizeof (char)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); goto FREE; } sprintf (string2, "DDSIP_exp_excess_SC%.3d", scen+1); scen_spec_rowname[scen] = string2; rmatbeg_stage[scen] = k; nzcnt_row = 2; rmatind_stage[k] = DDSIP_data->firstvar + DDSIP_param->scenarios*DDSIP_data->secvar + scen; rmatval_stage[k] = 1.; rmatind_stage[k + 1] = DDSIP_data->firstvar + DDSIP_param->scenarios*DDSIP_data->secvar + DDSIP_param->scenarios + scen; rmatval_stage[k + 1] = -1.; k += nzcnt_row; } if ((status = CPXaddrows(DDSIP_env, det_equ, 0, DDSIP_param->scenarios, k, det_equ_rhs, sense_sorted, rmatbeg_stage, rmatind_stage, rmatval_stage, NULL, scen_spec_rowname))) { fprintf (stderr, "CPXaddrows returned %d for second-stage risk constraints\n", status); goto FREE; } break; case 2: // Excess probability k = 0; for (scen = 0; scen < DDSIP_param->scenarios; scen++) { sense_sorted[scen] = 'L'; det_equ_rhs[scen] = DDSIP_param->risktarget; if (!(string2 = (char *) calloc (1, 255 * sizeof (char)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); goto FREE; } sprintf (string2, "DDSIP_excess_prob_SC%.3d", scen+1); scen_spec_rowname[scen] = string2; rmatbeg_stage[scen] = k; nzcnt_row = 2; rmatind_stage[k] = DDSIP_data->firstvar + DDSIP_param->scenarios*DDSIP_data->secvar + scen; rmatval_stage[k] = 1.; rmatind_stage[k + 1] = DDSIP_data->firstvar + DDSIP_param->scenarios*DDSIP_data->secvar + DDSIP_param->scenarios + scen; rmatval_stage[k + 1] = -DDSIP_param->riskM; k += nzcnt_row; } if ((status = CPXaddrows(DDSIP_env, det_equ, 0, DDSIP_param->scenarios, k, det_equ_rhs, sense_sorted, rmatbeg_stage, rmatind_stage, rmatval_stage, NULL, scen_spec_rowname))) { fprintf (stderr, "CPXaddrows returned %d for second-stage risk constraints\n", status); goto FREE; } break; case 4: // Worst case cost k = 0; for (scen = 0; scen < DDSIP_param->scenarios; scen++) { sense_sorted[scen] = 'L'; det_equ_rhs[scen] = 0.; if (!(string2 = (char *) calloc (1, 255 * sizeof (char)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); goto FREE; } sprintf (string2, "DDSIP_worst_case_SC%.3d", scen+1); scen_spec_rowname[scen] = string2; rmatbeg_stage[scen] = k; nzcnt_row = 2; rmatind_stage[k] = DDSIP_data->firstvar + DDSIP_param->scenarios*DDSIP_data->secvar + scen; rmatval_stage[k] = 1.; rmatind_stage[k + 1] = DDSIP_data->firstvar + DDSIP_param->scenarios*DDSIP_data->secvar + DDSIP_param->scenarios; rmatval_stage[k + 1] = -1.; k += nzcnt_row; } if ((status = CPXaddrows(DDSIP_env, det_equ, 0, DDSIP_param->scenarios, k, det_equ_rhs, sense_sorted, rmatbeg_stage, rmatind_stage, rmatval_stage, NULL, scen_spec_rowname))) { fprintf (stderr, "CPXaddrows returned %d for second-stage risk constraints\n", status); goto FREE; } break; } for (j = 0; j < DDSIP_param->scenarios; j++) DDSIP_Free ((void **) &(scen_spec_rowname[j])); time_end = DDSIP_GetCpuTime (); fprintf (DDSIP_outfile, " %6.2f sec for building deterministic equivalent\n",time_end-time_start); status = CPXwriteprob (DDSIP_env, det_equ, probname, NULL); if (status) { fprintf (DDSIP_outfile, " *** Deterministic equivalent not written successfully, status = %d\n", status); printf (" *** Deterministic equivalent not written successfully, status = %d\n", status); } else { fprintf (DDSIP_outfile, " *** Deterministic equivalent %s written successfully\n", probname); printf (" *** Deterministic equivalent %s written successfully\n", probname); } status = CPXfreeprob (DDSIP_env, &det_equ); time_start = DDSIP_GetCpuTime (); fprintf (DDSIP_outfile, " %6.2f sec for writing deterministic equivalent\n",time_start-time_end); FREE: DDSIP_Free ((void **) &(sense)); DDSIP_Free ((void **) &(sense_sorted)); DDSIP_Free ((void **) &(vartype)); DDSIP_Free ((void **) &(rowname)); DDSIP_Free ((void **) &(rownamestore)); DDSIP_Free ((void **) &(colname)); DDSIP_Free ((void **) &(colnamestore)); DDSIP_Free ((void **) &(det_equ_rhs)); DDSIP_Free ((void **) &(base_rhs)); DDSIP_Free ((void **) &(lb)); DDSIP_Free ((void **) &(ub)); DDSIP_Free ((void **) &(vartype_sorted)); DDSIP_Free ((void **) &(lb_sorted)); DDSIP_Free ((void **) &(ub_sorted)); DDSIP_Free ((void **) &(scaled_obj_coef)); DDSIP_Free ((void **) &(colindex_sorted)); DDSIP_Free ((void **) &(colindex_revers)); DDSIP_Free ((void **) &(scen_spec_rowname)); DDSIP_Free ((void **) &(scen_spec_colname)); DDSIP_Free ((void **) &(rmatbeg)); DDSIP_Free ((void **) &(rmatind)); DDSIP_Free ((void **) &(rmatval)); DDSIP_Free ((void **) &(rmatbeg_stage)); DDSIP_Free ((void **) &(rmatind_stage)); DDSIP_Free ((void **) &(rmatval_stage)); DDSIP_Free ((void **) &(rowindex)); if (ranged) { DDSIP_Free ((void **) &(rng)); DDSIP_Free ((void **) &(rng_sorted)); } return; }
long GenModelCplex::CreateModel() { if(!binit) return ThrowError("CreateModel() not available : Problem not initialized yet"); CplexData* d = (CplexData*)solverdata; int status = 0; d->nc = nc; d->nc = nc; d->onc = nc; d->onr = nr; if(boolParam.count("maximize") > 0 && boolParam["maximize"]) CPXchgobjsen (d->env, d->lp, CPX_MAX); else CPXchgobjsen (d->env, d->lp, CPX_MIN); d->lrhs = new double[nr]; d->urhs = new double[nr]; d->sense = new char[nr]; d->ub = new double[nc]; d->lb = new double[nc]; d->obj = new double[nc]; d->type = new char[nc]; d->mat_r = new int[nz]; d->mat_c = new int[nz]; d->mat_v = new double[nz]; d->cname = new char*[nc]; d->rname = new char*[nr]; nz=0; for(unsigned long i = 0; i < nr; i++) { d->rname[i] = new char[consts[i].name.length()+1]; snprintf(d->rname[i], consts[i].name.length()+1, "%s", consts[i].name.c_str()); //printf("%ld %s: ", i, consts[i].name.c_str()); for(unsigned long j = 0; j < consts[i].nz; j++) { d->mat_r[nz] = i; d->mat_c[nz] = consts[i].cols[j]; d->mat_v[nz] = consts[i].coefs[j]; //if(i >= 198) //printf("(%ld,%ld(%s),%f) ", d->mat_r[nz], d->mat_c[nz], vars.name[d->mat_c[nz]].c_str(), d->mat_v[nz]); nz++; } if(consts[i].lrhs == numeric_limits<double>::infinity()) d->lrhs[i] = CPX_INFBOUND; else if(consts[i].lrhs == -numeric_limits<double>::infinity()) d->lrhs[i] = -CPX_INFBOUND; else d->lrhs[i] = consts[i].lrhs; if(consts[i].urhs == numeric_limits<double>::infinity()) d->urhs[i] = CPX_INFBOUND; else if(consts[i].urhs == -numeric_limits<double>::infinity()) d->urhs[i] = -CPX_INFBOUND; else d->urhs[i] = consts[i].urhs-consts[i].lrhs; d->sense[i] = consts[i].sense; // printf("%ld/%ld -> %c\n", i, nr, d->sense[i]); } for(unsigned long i = 0; i < nc; i++) { d->cname[i] = new char[vars.name[i].length()+1]; snprintf(d->cname[i], vars.name[i].length()+1, "%s", vars.name[i].c_str()); d->obj[i] = vars.obj[i]; if(vars.ub[i] == numeric_limits<double>::infinity()) d->ub[i] = CPX_INFBOUND; else if(vars.ub[i] == -numeric_limits<double>::infinity()) d->ub[i] = -CPX_INFBOUND; else d->ub[i] = vars.ub[i]; if(vars.lb[i] == numeric_limits<double>::infinity()) d->lb[i] = CPX_INFBOUND; else if(vars.lb[i] == -numeric_limits<double>::infinity()) d->lb[i] = -CPX_INFBOUND; else d->lb[i] = vars.lb[i]; d->type[i] = vars.type[i]; //printf("%ld (%s) -> %f %f %f %c\n", i, vars.name[i].c_str(), d->obj[i], d->lb[i], d->ub[i], d->type[i]); } status = CPXnewrows (d->env, d->lp, nr, d->lrhs, d->sense, d->urhs, d->rname); if ( status ) { char errmsg[1024]; fprintf (stderr, "Could not create new rows.\n"); CPXgeterrorstring (d->env, status, errmsg); fprintf (stderr, "%s", errmsg); return 1; } //else //printf("Row added!\n"); if(boolParam.count("mip") > 0 && boolParam["mip"]) status = CPXnewcols (d->env, d->lp, nc, d->obj, d->lb, d->ub, d->type, d->cname); else status = CPXnewcols (d->env, d->lp, nc, d->obj, d->lb, d->ub, NULL, NULL); if ( status ) { char errmsg[1024]; fprintf (stderr, "Could not create new cols.\n"); CPXgeterrorstring (d->env, status, errmsg); fprintf (stderr, "%s", errmsg); return 1; } //status = CPXnewcols (env, lp, nc, obj, lb, ub, NULL, colname); if ( status ) return 1; //else //printf("Col added!\n"); status = CPXchgcoeflist (d->env, d->lp, nz, d->mat_r, d->mat_c, d->mat_v); if ( status ) return 1; vector<long>::iterator iti; vector<long>::iterator itj = vars.qj.begin(); vector<double>::iterator itv = vars.qobj.begin(); vector<vector<pair<int,double> > > qptemp; qptemp.resize(nc); int* qpbeg = NULL; int* qpnum = NULL; int* qpind = NULL; double* qpv = NULL; int qpnz = 0; if(!vars.qi.empty()) { boolParam["qp"] = true; qpbeg = new int[nc]; qpnum = new int[nc]; } if(boolParam.count("qp_mat") == 0 || boolParam["qp_mat"]) { for(iti = vars.qi.begin(); iti != vars.qi.end(); iti++, itj++, itv++) { qptemp[*iti].push_back(pair<int, double>(*itj,*itv)); qpnz++; if(*iti != *itj) { qptemp[*itj].push_back(pair<int, double>(*iti,*itv)); qpnz++; } } if(!vars.qi.empty()) { qpv = new double[qpnz]; qpind = new int[qpnz]; qpnz=0; for(int i = 0; i < int(nc); i++) { qpbeg[i] = qpnz; qpnum[i] = int(qptemp[i].size()); for(int j = 0; j < int(qptemp[i].size()); j++) { qpind[qpnz] = qptemp[i][j].first; qpv[qpnz] = 2.0*qptemp[i][j].second; qpnz++; } } status = CPXcopyquad(d->env, d->lp, qpbeg, qpnum, qpind, qpv); delete[] qpbeg; delete[] qpnum; delete[] qpind; delete[] qpv; } if ( status ) { printf("QP problem!\n"); return 1; } } //else //printf("Coefs added!\n"); bcreated = true; return 0; }
void IPBuild() { int status; char *pVarType; double *pdLB, *pdUB, *pdObj, *pdrhs, *pdVal; unsigned int NbPyr=PYRGetNumbers(),TotJob=0, *puiBeg, *puiInd,uiJob,NbJobBefore; unsigned int uiLoop,uiLoop2,uiLoop3,uiIndice; // Initialize and configure the IP environment IPInitialize(); // We now create the model //strcpy (probname, "1riLmax"); lp = CPXcreateprob (env, &status, ""); if ( lp == NULL ) { printf ("Failed to create LP.\n"); getch(); exit(-1); } // We create the variables printf("\t Variable creation\n"); pVarName=(char **)malloc(sizeof(char *)*(1+2*NbPyr+2*NbPyr*(NbJobs-NbPyr))); for (uiLoop=0;uiLoop<(1+2*NbPyr+2*NbPyr*(NbJobs-NbPyr));uiLoop++) pVarName[uiLoop]=(char *)malloc(sizeof(char)*700); pVarType=(char *)malloc(sizeof(char )*(1+2*NbPyr+2*NbPyr*(NbJobs-NbPyr))); pdLB=(double *)malloc(sizeof(double)*(1+2*NbPyr+2*NbPyr*(NbJobs-NbPyr))); pdUB=(double *)malloc(sizeof(double)*(1+2*NbPyr+2*NbPyr*(NbJobs-NbPyr))); pdObj=(double *)malloc(sizeof(double)*(1+2*NbPyr+2*NbPyr*(NbJobs-NbPyr))); strcpy(pVarName[0],"Lmax"); pVarType[0]='C'; pdLB[0]=-INFTY; pdUB[0]=INFTY; pdObj[0]=1; for (uiLoop=0;uiLoop<NbPyr;uiLoop++) { char cBuf[10000]; strcpy(pVarName[1+2*uiLoop],"R"); sprintf(cBuf,"%d",uiLoop); strcat(pVarName[1+2*uiLoop],cBuf); pVarType[1+2*uiLoop]='C'; pdLB[1+2*uiLoop]=(double)ri(PYRGetTopJob(uiLoop)); pdUB[1+2*uiLoop]=INFTY; pdObj[1+2*uiLoop]=0; strcpy(pVarName[1+2*uiLoop+1],"D"); sprintf(cBuf,"%d",uiLoop); strcat(pVarName[1+2*uiLoop+1],cBuf); pVarType[1+2*uiLoop+1]='C'; pdLB[1+2*uiLoop+1]=-INFTY; pdUB[1+2*uiLoop+1]=(double)di(PYRGetTopJob(uiLoop)); pdObj[1+2*uiLoop+1]=0; } TotJob=0; for (uiLoop=0;uiLoop<NbPyr;uiLoop++) { for (uiLoop2=0;uiLoop2<PYRGetNumberJobs(uiLoop);uiLoop2++) { char cBuf[10000]; strcpy(pVarName[1+2*NbPyr+TotJob+2*uiLoop2],"xm"); sprintf(cBuf,"%d,%d",uiLoop,PYRGetJobsInPyr(uiLoop,uiLoop2)); strcat(pVarName[1+2*NbPyr+TotJob+2*uiLoop2],cBuf); //printf("%s \n",pVarName[1+2*NbPyr+TotJob+2*uiLoop2]); pVarType[1+2*NbPyr+TotJob+2*uiLoop2]='B'; pdLB[1+2*NbPyr+TotJob+2*uiLoop2]=-INFTY; pdUB[1+2*NbPyr+TotJob+2*uiLoop2]=INFTY; pdObj[1+2*NbPyr+TotJob+2*uiLoop2]=0; strcpy(pVarName[1+2*NbPyr+TotJob+2*uiLoop2+1],"xp"); sprintf(cBuf,"%d,%d",uiLoop,PYRGetJobsInPyr(uiLoop,uiLoop2)); strcat(pVarName[1+2*NbPyr+TotJob+2*uiLoop2+1],cBuf); //printf("%s \n",pVarName[1+2*NbPyr+TotJob+2*uiLoop2+1]); pVarType[1+2*NbPyr+TotJob+2*uiLoop2+1]='B'; pdLB[1+2*NbPyr+TotJob+2*uiLoop2+1]=-INFTY; pdUB[1+2*NbPyr+TotJob+2*uiLoop2+1]=INFTY; pdObj[1+2*NbPyr+TotJob+2*uiLoop2+1]=0; } TotJob+=2*PYRGetNumberJobs(uiLoop); } uiNbVar=1+2*NbPyr+TotJob; status = CPXnewcols (env, lp, uiNbVar, pdObj, pdLB, pdUB, pVarType, pVarName); // We now create constraints // First: Lmax>=Rk+ptk-Dk, forall k=1..NbPyr printf("\t Creating constraints 1\n"); pdrhs=(double *)malloc(sizeof(double)*1); puiBeg=(unsigned int *)malloc(sizeof(unsigned int)*1); puiBeg[0]=0; puiInd=(unsigned int *)malloc(sizeof(unsigned int)*3); pdVal=(double *)malloc(sizeof(double)*3); for (uiLoop=0;uiLoop<NbPyr;uiLoop++) { puiInd[0]=0; pdVal[0]=-1.0; puiInd[1]=1+2*uiLoop; pdVal[1]=1.0; puiInd[2]=1+2*uiLoop+1; pdVal[2]=-1.0; pdrhs[0]=-1.0*(double)pi(PYRGetTopJob(uiLoop)); status = CPXaddrows (env, lp, 0, 1, 3, pdrhs, "L", (const int *)puiBeg, (const int*)puiInd, (const double *)pdVal, NULL, NULL); } free(pdrhs); free(puiBeg); free(puiInd); free(pdVal); // Second: Rk>=ri+sum pjxpkj, forall i|k=U(i) printf("\t Creating constraints 2\n"); pdrhs=(double *)malloc(sizeof(double)*1); puiBeg=(unsigned int *)malloc(sizeof(unsigned int)*1); puiBeg[0]=0; NbJobBefore=0; for(uiLoop=0;uiLoop<NbPyr;uiLoop++) { puiInd=(unsigned int *)malloc(sizeof(unsigned int)*(1+PYRGetNumberJobs(uiLoop))); pdVal=(double *)malloc(sizeof(double)*(1+PYRGetNumberJobs(uiLoop))); for (uiLoop2=0;uiLoop2<NbJobs;uiLoop2++) if (U[uiLoop2]==(signed int)uiLoop) { // We add the constraint puiInd[0]=1+2*uiLoop; pdVal[0]=-1.0; pdrhs[0]=-1.0*(double)ri(uiLoop2); TotJob=0; for (uiLoop3=0;uiLoop3<PYRGetNumberJobs(uiLoop);uiLoop3++) { uiJob=PYRGetJobsInPyr(uiLoop,uiLoop3); if ((ri(uiJob)>ri(uiLoop2))||(ri(uiJob)==ri(uiLoop2) && di(uiJob)>di(uiLoop2))||(ri(uiJob)==ri(uiLoop2) && di(uiJob)==di(uiLoop2) && uiLoop2<=uiJob)) { TotJob++; puiInd[TotJob]=1+2*NbPyr+2*NbJobBefore+2*uiLoop3+1; pdVal[TotJob]=(double)pi(uiJob); } } status = CPXaddrows (env, lp, 0, 1, 1+TotJob, pdrhs, "L", (const int *)puiBeg, (const int*)puiInd, (const double *)pdVal, NULL, NULL); } NbJobBefore+=PYRGetNumberJobs(uiLoop); free(pdVal); free(puiInd); } free(pdrhs); free(puiBeg); // Third: Dk<=di-sum pjxmkj, forall i|k=V(i) printf("\t Creating constraints 3\n"); pdrhs=(double *)malloc(sizeof(double)*1); puiBeg=(unsigned int *)malloc(sizeof(unsigned int)*1); puiBeg[0]=0; NbJobBefore=0; for(uiLoop=0;uiLoop<NbPyr;uiLoop++) { puiInd=(unsigned int *)malloc(sizeof(unsigned int)*(1+PYRGetNumberJobs(uiLoop))); pdVal=(double *)malloc(sizeof(double)*(1+PYRGetNumberJobs(uiLoop))); for (uiLoop2=0;uiLoop2<NbJobs;uiLoop2++) if (V[uiLoop2]==(signed int) uiLoop) { // We add the constraint puiInd[0]=1+2*uiLoop+1; pdVal[0]=1.0; pdrhs[0]=(double)di(uiLoop2); TotJob=0; for (uiLoop3=0;uiLoop3<PYRGetNumberJobs(uiLoop);uiLoop3++) { uiJob=PYRGetJobsInPyr(uiLoop,uiLoop3); if ((di(uiJob)<di(uiLoop2))||(di(uiJob)==di(uiLoop2) && ri(uiJob)<ri(uiLoop2))||(ri(uiJob)==ri(uiLoop2) && di(uiJob)==di(uiLoop2) && uiLoop2>=uiJob)) { TotJob++; puiInd[TotJob]=1+2*NbPyr+2*NbJobBefore+2*uiLoop3; pdVal[TotJob]=(double)pi(uiJob); } } status = CPXaddrows (env, lp, 0, 1, 1+TotJob, pdrhs, "L", (const int *)puiBeg, (const int*)puiInd, (const double *)pdVal, NULL, NULL); } NbJobBefore+=PYRGetNumberJobs(uiLoop); free(pdVal); free(puiInd); } free(pdrhs); free(puiBeg); // Fourth: sum xpkj+xmkj=1, forall i printf("\t Creating constraints 4\n"); pdrhs=(double *)malloc(sizeof(double)*1); pdrhs[0]=1; puiBeg=(unsigned int *)malloc(sizeof(unsigned int)*1); puiBeg[0]=0; for(uiLoop=0;uiLoop<NbJobs;uiLoop++) if (U[uiLoop]!=-1) { puiInd=(unsigned int *)malloc(sizeof(unsigned int)*2*(V[uiLoop]-U[uiLoop]+1)); pdVal=(double *)malloc(sizeof(double)*2*(V[uiLoop]-U[uiLoop]+1)); NbJobBefore=0; for (uiLoop2=0;uiLoop2<U[uiLoop];uiLoop2++) NbJobBefore+=PYRGetNumberJobs(uiLoop2); uiIndice=0; for (uiLoop2=U[uiLoop];uiLoop2<=V[uiLoop];uiLoop2++) { puiInd[uiIndice]=1+2*PYRGetNumbers()+2*NbJobBefore+PYRGetJobPos(uiLoop2,uiLoop)*2; pdVal[uiIndice]=1.0; uiIndice++; puiInd[uiIndice]=1+2*PYRGetNumbers()+2*NbJobBefore+PYRGetJobPos(uiLoop2,uiLoop)*2+1; pdVal[uiIndice]=1.0; uiIndice++; NbJobBefore+=PYRGetNumberJobs(uiLoop2); } status = CPXaddrows (env, lp, 0, 1, 2*(V[uiLoop]-U[uiLoop]+1), pdrhs, "E", (const int *)puiBeg, (const int*)puiInd, (const double *)pdVal, NULL, NULL); free(puiInd); free(pdVal); } free(puiBeg); free(pdrhs); // Fifth: Rk>=Rk-1 + sum pjxm(k-1)j + ptk-1 + sum pjxpkj, forall k=2...NbPyr printf("\t Creating constraints 5\n"); pdrhs=(double *)malloc(sizeof(double)*1); puiBeg=(unsigned int *)malloc(sizeof(unsigned int)*1); puiBeg[0]=0; NbJobBefore=0; for(uiLoop=1;uiLoop<NbPyr;uiLoop++) { puiInd=(unsigned int *)malloc(sizeof(unsigned int)*(2+PYRGetNumberJobs(uiLoop-1)+PYRGetNumberJobs(uiLoop))); pdVal=(double *)malloc(sizeof(double)*(2+PYRGetNumberJobs(uiLoop-1)+PYRGetNumberJobs(uiLoop))); pdrhs[0]=-1.0*(double)pi(PYRGetTopJob(uiLoop-1)); puiInd[0]=1+2*(uiLoop-1); pdVal[0]=1.0; puiInd[1]=1+2*uiLoop; pdVal[1]=-1.0; for (uiLoop2=0;uiLoop2<PYRGetNumberJobs(uiLoop-1);uiLoop2++) { puiInd[2+uiLoop2]=1+2*NbPyr+2*NbJobBefore+2*uiLoop2; pdVal[2+uiLoop2]=(double)pi(PYRGetJobsInPyr(uiLoop-1,uiLoop2)); } NbJobBefore+=PYRGetNumberJobs(uiLoop-1); for (uiLoop2=0;uiLoop2<PYRGetNumberJobs(uiLoop);uiLoop2++) { puiInd[2+PYRGetNumberJobs(uiLoop-1)+uiLoop2]=1+2*NbPyr+2*NbJobBefore+2*uiLoop2+1; pdVal[2+PYRGetNumberJobs(uiLoop-1)+uiLoop2]=(double)pi(PYRGetJobsInPyr(uiLoop,uiLoop2)); } status = CPXaddrows (env, lp, 0, 1, 2+PYRGetNumberJobs(uiLoop)+PYRGetNumberJobs(uiLoop-1), pdrhs, "L", (const int *)puiBeg, (const int*)puiInd, (const double *)pdVal, NULL, NULL); free(pdVal); free(puiInd); } free(pdrhs); free(puiBeg); // Sixth: Dk<=Dk+1 - sum pjxp(k+1)j - ptk+1 - sum pjxmkj, forall k=1...NbPyr-1 printf("\t Creating constraints 6\n"); pdrhs=(double *)malloc(sizeof(double)*1); puiBeg=(unsigned int *)malloc(sizeof(unsigned int)*1); puiBeg[0]=0; NbJobBefore=0; for(uiLoop=0;uiLoop<NbPyr-1;uiLoop++) { puiInd=(unsigned int *)malloc(sizeof(unsigned int)*(2+PYRGetNumberJobs(uiLoop)+PYRGetNumberJobs(uiLoop+1))); pdVal=(double *)malloc(sizeof(double)*(2+PYRGetNumberJobs(uiLoop)+PYRGetNumberJobs(uiLoop+1))); pdrhs[0]=(double)pi(PYRGetTopJob(uiLoop+1)); puiInd[0]=1+2*(uiLoop+1)+1; pdVal[0]=1.0; puiInd[1]=1+2*uiLoop+1; pdVal[1]=-1.0; for (uiLoop2=0;uiLoop2<PYRGetNumberJobs(uiLoop);uiLoop2++) { puiInd[2+uiLoop2]=1+2*NbPyr+2*NbJobBefore+2*uiLoop2; pdVal[2+uiLoop2]=-1.0*(double)pi(PYRGetJobsInPyr(uiLoop,uiLoop2)); } NbJobBefore+=PYRGetNumberJobs(uiLoop); for (uiLoop2=0;uiLoop2<PYRGetNumberJobs(uiLoop+1);uiLoop2++) { puiInd[2+PYRGetNumberJobs(uiLoop)+uiLoop2]=1+2*NbPyr+2*NbJobBefore+2*uiLoop2+1; pdVal[2+PYRGetNumberJobs(uiLoop)+uiLoop2]=-1.0*(double)pi(PYRGetJobsInPyr(uiLoop+1,uiLoop2)); } status = CPXaddrows (env, lp, 0, 1, 2+PYRGetNumberJobs(uiLoop)+PYRGetNumberJobs(uiLoop+1), pdrhs, "G", (const int *)puiBeg, (const int*)puiInd, (const double *)pdVal, NULL, NULL); free(pdVal); free(puiInd); } free(pdrhs); free(puiBeg); }
int main (void) { int status, solstat; CPXENVptr env; CPXLPptr lp; int i; double x[NUMCOLS]; double cpi[NUMCOLS]; double rpi[NUMROWS]; double qpi[NUMQS]; double slack[NUMROWS], qslack[NUMQS]; double kktsum[NUMCOLS]; /* ********************************************************************** * * * * S E T U P P R O B L E M * * * * ********************************************************************** */ /* Create CPLEX environment and enable screen output. */ env = CPXopenCPLEX (&status); if ( status != 0 ) goto TERMINATE; status = CPXsetintparam (env, CPXPARAM_ScreenOutput, CPX_ON); if ( status != 0 ) goto TERMINATE; /* Create the problem object and populate it. */ lp = CPXcreateprob (env, &status, "qcpdual"); if ( status != 0 ) goto TERMINATE; status = CPXnewcols (env, lp, NUMCOLS, obj, lb, ub, NULL, cname); if ( status != 0 ) goto TERMINATE; status = CPXaddrows (env, lp, 0, NUMROWS, NUMNZS, rhs, sense, rmatbeg, rmatind, rmatval, NULL, rname); if ( status != 0 ) goto TERMINATE; for (i = 0; i < NUMQS; ++i) { int const linend = (i == NUMQS - 1) ? NUMLINNZ : linbeg[i + 1]; int const quadend = (i == NUMQS - 1) ? NUMQUADNZ : quadbeg[i + 1]; status = CPXaddqconstr (env, lp, linend - linbeg[i], quadend - quadbeg[i], qrhs[i], qsense[i], &linind[linbeg[i]], &linval[linbeg[i]], &quadrow[quadbeg[i]], &quadcol[quadbeg[i]], &quadval[quadbeg[i]], qname[i]); if ( status != 0 ) goto TERMINATE; } /* ********************************************************************** * * * * O P T I M I Z E P R O B L E M * * * * ********************************************************************** */ status = CPXsetdblparam (env, CPXPARAM_Barrier_QCPConvergeTol, 1e-10); if ( status != 0 ) goto TERMINATE; /* Solve the problem. */ status = CPXbaropt (env, lp); if ( status != 0 ) goto TERMINATE; solstat = CPXgetstat (env, lp); if ( solstat != CPX_STAT_OPTIMAL ) { fprintf (stderr, "No optimal solution found!\n"); goto TERMINATE; } /* ********************************************************************** * * * * Q U E R Y S O L U T I O N * * * * ********************************************************************** */ /* Optimal solution and slacks for linear and quadratic constraints. */ status = CPXgetx (env, lp, x, 0, NUMCOLS - 1); if ( status != 0 ) goto TERMINATE; status = CPXgetslack (env, lp, slack, 0, NUMROWS - 1); if ( status != 0 ) goto TERMINATE; status = CPXgetqconstrslack (env, lp, qslack, 0, NUMQS - 1); if ( status != 0 ) goto TERMINATE; /* Dual multipliers for linear constraints and bound constraints. */ status = CPXgetdj (env, lp, cpi, 0, NUMCOLS - 1); if ( status != 0 ) goto TERMINATE; status = CPXgetpi (env, lp, rpi, 0, NUMROWS - 1); if ( status != 0 ) goto TERMINATE; status = getqconstrmultipliers (env, lp, x, qpi, ZEROTOL); if ( status != 0 ) goto TERMINATE; /* ********************************************************************** * * * * C H E C K K K T C O N D I T I O N S * * * * Here we verify that the optimal solution computed by CPLEX (and * * the qpi[] values computed above) satisfy the KKT conditions. * * * * ********************************************************************** */ /* Primal feasibility: This example is about duals so we skip this test. */ /* Dual feasibility: We must verify * - for <= constraints (linear or quadratic) the dual * multiplier is non-positive. * - for >= constraints (linear or quadratic) the dual * multiplier is non-negative. */ for (i = 0; i < NUMROWS; ++i) { switch (sense[i]) { case 'E': /* nothing */ break; case 'R': /* nothing */ break; case 'L': if ( rpi[i] > ZEROTOL ) { fprintf (stderr, "Dual feasibility test failed for <= row %d: %f\n", i, rpi[i]); status = -1; goto TERMINATE; } break; case 'G': if ( rpi[i] < -ZEROTOL ) { fprintf (stderr, "Dual feasibility test failed for >= row %d: %f\n", i, rpi[i]); status = -1; goto TERMINATE; } break; } } for (i = 0; i < NUMQS; ++i) { switch (qsense[i]) { case 'E': /* nothing */ break; case 'L': if ( qpi[i] > ZEROTOL ) { fprintf (stderr, "Dual feasibility test failed for <= quad %d: %f\n", i, qpi[i]); status = -1; goto TERMINATE; } break; case 'G': if ( qpi[i] < -ZEROTOL ) { fprintf (stderr, "Dual feasibility test failed for >= quad %d: %f\n", i, qpi[i]); status = -1; goto TERMINATE; } break; } } /* Complementary slackness. * For any constraint the product of primal slack and dual multiplier * must be 0. */ for (i = 0; i < NUMROWS; ++i) { if ( sense[i] != 'E' && fabs (slack[i] * rpi[i]) > ZEROTOL ) { fprintf (stderr, "Complementary slackness test failed for row %d: %f\n", i, fabs (slack[i] * rpi[i])); status = -1; goto TERMINATE; } } for (i = 0; i < NUMQS; ++i) { if ( qsense[i] != 'E' && fabs (qslack[i] * qpi[i]) > ZEROTOL ) { fprintf (stderr, "Complementary slackness test failed for quad %d: %f\n", i, fabs (qslack[i] * qpi[i])); status = -1; goto TERMINATE; } } for (i = 0; i < NUMCOLS; ++i) { if ( ub[i] < CPX_INFBOUND ) { double const slk = ub[i] - x[i]; double const dual = cpi[i] < -ZEROTOL ? cpi[i] : 0.0; if ( fabs (slk * dual) > ZEROTOL ) { fprintf (stderr, "Complementary slackness test failed for ub %d: %f\n", i, fabs (slk * dual)); status = -1; goto TERMINATE; } } if ( lb[i] > -CPX_INFBOUND ) { double const slk = x[i] - lb[i]; double const dual = cpi[i] > ZEROTOL ? cpi[i] : 0.0; if ( fabs (slk * dual) > ZEROTOL ) { printf ("lb=%f, x=%f, cpi=%f\n", lb[i], x[i], cpi[i]); fprintf (stderr, "Complementary slackness test failed for lb %d: %f\n", i, fabs (slk * dual)); status = -1; goto TERMINATE; } } } /* Stationarity. * The difference between objective function and gradient at optimal * solution multiplied by dual multipliers must be 0, i.e., for the * optimal solution x * 0 == c * - sum(r in rows) r'(x)*rpi[r] * - sum(q in quads) q'(x)*qpi[q] * - sum(c in cols) b'(x)*cpi[c] * where r' and q' are the derivatives of a row or quadratic constraint, * x is the optimal solution and rpi[r] and qpi[q] are the dual * multipliers for row r and quadratic constraint q. * b' is the derivative of a bound constraint and cpi[c] the dual bound * multiplier for column c. */ /* Objective function. */ for (i = 0; i < NUMCOLS; ++i) kktsum[i] = obj[i]; /* Linear constraints. * The derivative of a linear constraint ax - b (<)= 0 is just a. */ for (i = 0; i < NUMROWS; ++i) { int const end = (i == NUMROWS - 1) ? NUMNZS : rmatbeg[i + 1]; int k; for (k = rmatbeg[i]; k < end; ++k) kktsum[rmatind[k]] -= rpi[i] * rmatval[k]; } /* Quadratic constraints. * The derivative of a constraint xQx + ax - b <= 0 is * Qx + Q'x + a. */ for (i = 0; i < NUMQS; ++i) { int j; int k; for (j = linbeg[i]; j < linbeg[i] + linnzcnt[i]; ++j) kktsum[linind[j]] -= qpi[i] * linval[j]; for (k = quadbeg[i]; k < quadbeg[i] + quadnzcnt[i]; ++k) { kktsum[quadrow[k]] -= qpi[i] * x[quadcol[k]] * quadval[k]; kktsum[quadcol[k]] -= qpi[i] * x[quadrow[k]] * quadval[k]; } } /* Bounds. * The derivative for lower bounds is -1 and that for upper bounds * is 1. * CPLEX already returns dj with the appropriate sign so there is * no need to distinguish between different bound types here. */ for (i = 0; i < NUMCOLS; ++i) { kktsum[i] -= cpi[i]; } for (i = 0; i < NUMCOLS; ++i) { if ( fabs (kktsum[i]) > ZEROTOL ) { fprintf (stderr, "Stationarity test failed at index %d: %f\n", i, kktsum[i]); status = -1; goto TERMINATE; } } /* KKT conditions satisfied. Dump out the optimal solutions and * the dual values. */ printf ("Optimal solution satisfies KKT conditions.\n"); printf (" x[] ="); for (i = 0; i < NUMCOLS; ++i) printf (" %7.3f", x[i]); printf ("\n"); printf ("cpi[] ="); for (i = 0; i < NUMCOLS; ++i) printf (" %7.3f", cpi[i]); printf ("\n"); printf ("rpi[] ="); for (i = 0; i < NUMROWS; ++i) printf (" %7.3f", rpi[i]); printf ("\n"); printf ("qpi[] ="); for (i = 0; i < NUMQS; ++i) printf (" %7.3f", qpi[i]); printf ("\n"); TERMINATE: /* ********************************************************************** * * * * C L E A N U P * * * * ********************************************************************** */ status = CPXfreeprob (env, &lp); if ( status != 0 ) { fprintf (stderr, "WARNING: Failed to free problem: %d\n", status); } status = CPXcloseCPLEX (&env); if ( status != 0 ) { fprintf (stderr, "WARNING: Failed to close CPLEX: %d\n", status); } return status; }
SSCplex::SSCplex( string InstanceFile ) { num_vm = 0; // number of virtual machines num_vf = 0; // number of virtual function int offset; ifstream in; in.open(InstanceFile.c_str()); if( !in.is_open() ) { cout<<"Cannot open instance file.\n"; exit(1); } //leggo da file il numero di macchine e di funzioni virtuali in >> num_vm; in >> num_vf; cout << "Num VM " << num_vm << " Num VF " << num_vf << endl; lev_card = num_vm; // the number of nodes in each level h_len = num_vf; int lev_card_arcs = lev_card*lev_card; //number of nodes and arcs NNodes = lev_card * h_len + 2; NArcs = lev_card * lev_card * (h_len-1) + 2*lev_card; // array used to store the solution Y = array(NArcs); tempi_lat = new double *[num_vm]; for (int i=0; i<num_vm; i++) tempi_lat[i] = new double[num_vm]; cap = new int[ num_vm ]; // fill the distance matrix for (int i=0; i<num_vm; i++) for (int j=0; j<num_vm; j++) // if( j >= i ) in >> tempi_lat[i][j]; // else (in input is supposed to be symmetric) // tempi_lat[i][j] = tempi_lat[j][i]; // fill the capacity array for (int i=0; i<num_vm; i++) in >> cap[ i ]; incom = new int *[num_vf]; for (int i=0; i<num_vf; i++) incom[i] = new int[num_vm+1]; proc_time = new double *[num_vf]; for (int i=0; i<num_vf; i++) proc_time[i] = new double[num_vm]; for( int i = 0; i < num_vf; i++ ) { string dummy; int cnt; in >> dummy >> incom[i][0]; cnt = incom[i][0]; for( int j = 1; j <= cnt; j++ ) in >> incom[i][j]; for( int j = 0; j < num_vm; j++ ) in >> proc_time[i][j]; } source_dist = new double[ num_vm ]; dest_dist = new double[ num_vm ]; for( int j = 0; j < num_vm; j++ ) in >> source_dist[j]; for( int j = 0; j < num_vm; j++ ) in >> dest_dist[j]; in.close(); /* Initialize the CPLEX environment */ env = CPXopenCPLEX (&status); if ( env == NULL ) { stop("Could not open CPLEX environment.\n", status); } /* Create the problem */ lp = CPXcreateprob( env , &status , "HCP" ); if ( lp == NULL ) { stop("Failed to create LP.\n", status); } if( DEBUG ) { CPXout.open("DEBUG.txt", ios::out); } // Turn on debugging routines status = CPXsetintparam (env, CPX_PARAM_DATACHECK, CPX_ON); if ( status ) { stop("Failure to turn on debugging, error %d.\n", status); } // Turn on output to the screen status = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_ON); if ( status ) { stop("Failure to turn on screen indicator, error %d.\n", status); } double *obj = NULL; double *ub = NULL; double *lb = NULL; char *ctype = NULL; int nzcnt; double *rhs = NULL; char *sense = NULL; int *matbeg; int *matind; double *matval; // variable counters int y_var = NArcs; // flow variables // creating variables ub = array(y_var); lb = array(y_var); for( int k = 0; k < y_var; k++ ){ lb[k] = 0.0; ub[ k ] = 1.0; } #if( MIP ) ctype = arraychar(y_var); for( int h = 0; h < y_var; h++) ctype[h] = 'B'; #endif obj = array(NArcs); for(int i = 0; i < lev_card; i++ ) obj[i] = proc_time[0][i] + source_dist[i]; offset = lev_card * lev_card * (h_len-1) + lev_card; for(int i = 0; i < lev_card; i++ ) obj[offset+i] = dest_dist[i]; offset = lev_card; for( int h = 0; h < h_len - 1; h++ ) for( int i = 0; i < lev_card; i++ ) for( int j = 0; j < lev_card; j++ ) { int k = offset + h * (lev_card * lev_card) + i * lev_card + j; obj[k] = tempi_lat[i][j] + proc_time[h+1][j]; } status = CPXnewcols(env, lp, y_var, obj, lb, ub, ctype, NULL); if ( status ) stop("Failure to create y cols.", status); nzcnt = NArcs; matind = arrayint(nzcnt); matval = array(nzcnt); matbeg = arrayint(2); rhs = array(1); // at most one constraint is loaded sense = arraychar(1); // in one shot matbeg[0] = 0; // flow conservation constraint relative to source node rhs[0] = 1.0; sense[0] = 'E'; for( int h = 0; h < lev_card; h++ ) { matind[h] = h; matval[h] = 1.0; } matbeg[1] = lev_card; status = CPXaddrows(env, lp, 0, 1, lev_card, rhs, sense, matbeg, matind, matval, NULL, NULL); if ( status ) { stop("Failed to insert cons.\n", status); } offset = lev_card + (h_len - 1) * (lev_card * lev_card); // flow conservation constraint relative to destination node for( int h = 0; h < lev_card; h++ ) { matind[h] = offset + h; matval[h] = 1.0; } matbeg[1] = lev_card; status = CPXaddrows(env, lp, 0, 1, lev_card, rhs, sense, matbeg, matind, matval, NULL, NULL); if ( status ) { stop("Failed to insert cons.\n", status); } // flow conservation constraints relative to intermediate nodes rhs[0] = 0.0; for( int h = 0; h < h_len; h++ ) { for( int i = 0; i < lev_card; i++ ) { int k = 0; // insert a constraint for each intermediate node // incoming flow if( h == 0 ) { matind[k] = i; matval[k] = -1.0; k++; } else { offset = lev_card + lev_card*lev_card*(h-1); for( int j = 0; j < lev_card; j++ ) { matind[k] = offset + j * lev_card + i; matval[k] = -1.0; k++; } } // outcoming flow if( h == h_len - 1) { offset = lev_card + lev_card*lev_card*h; matind[k] = offset + i; matval[k] = 1.0; k++; } else { offset = lev_card + lev_card*lev_card*h; for( int j = 0; j < lev_card; j++ ) { matind[k] = offset + i*lev_card + j; matval[k] = 1.0; k++; } } matbeg[1] = k; assert( k <= nzcnt ); status = CPXaddrows(env, lp, 0, 1, k, rhs, sense, matbeg, matind, matval, NULL, NULL); if ( status ) { stop("Failed to insert cons.\n", status); } } } // VM capacity constraints sense[0] = 'L'; for( int i = 0; i < lev_card; i++ ) { int k = 0; // insert a constraint for each VM rhs[0] = cap[i]; for( int h = 0; h < h_len - 1; h++ ) { offset = lev_card + lev_card*lev_card*h; for( int j = 0; j < lev_card; j++ ) { matind[k] = offset + i*lev_card + j; matval[k] = 1.0; k++; } } offset = lev_card + lev_card*lev_card*(h_len-1); matind[k] = offset + i; matval[k] = 1.0; k++; matbeg[1] = k; assert( k <= nzcnt ); status = CPXaddrows(env, lp, 0, 1, k, rhs, sense, matbeg, matind, matval, NULL, NULL); if ( status ) { stop("Failed to insert cons.\n", status); } } // incompatibilities management // vf_0 int cnt = incom[0][0]; for( int j = 0; j < cnt; j++ ) { int arc_index = incom[0][j+1]; ChgBds(arc_index, 0.0); } // other vf_h for( int h = 1; h < num_vf; h++ ) { int cnt = incom[h][0]; int offset = lev_card + (h-1) * (lev_card*lev_card); for( int j = 0; j < cnt; j++ ) for( int i = 0; i < lev_card; i++ ) { int arc_index = offset + i * lev_card + incom[h][j+1]; ChgBds(arc_index, 0.0); } } #if DEBUG status = CPXwriteprob(env, lp, "SS.lp", "LP"); if ( status ) stop("Failed to write LP to disk.", status); #endif /* Set limit to emphasize feasibility */ status = CPXsetintparam (env, CPX_PARAM_MIPEMPHASIS, MIPEMPH); if ( status ) stop("Failure to set parameter emphasizing feasibility.\n", status); // Turn on output to the screen status = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_ON); if ( status ) { stop("Failure to turn on screen indicator, error %d.\n", status); } status = CPXsetdblparam (env, CPX_PARAM_TILIM, TIMELIMIT); free_arraychar(sense); free_array(rhs); free_arrayint(matbeg); free_array(matval); free_arrayint(matind); free_array(obj); #if( MIP ) free_arraychar(ctype); #endif free_array(lb); free_array(ub); } //END SSCplex
void DDSIP_DetEqu () { CPXLPptr det_equ; int status, scen, i, j, k; char probname[] = "sipout/det_equ.lp.gz"; double *obj_coef; double *scaled_obj_coef; char *sense; char **scen_spec_rowname; char **scen_spec_colname; char **rowname, *rownamestore; char **colname, *colnamestore; int rowstorespace, rowsurplus_p; int colstorespace, colsurplus_p; char *string1, *string2; double coef; double *lb, *lb_sorted; double *ub, *ub_sorted; char *vartype, *vartype_sorted; int *colindex_sorted, *colindex_revers, *matcol_sorted; double *value; double *det_equ_rhs = NULL; double *non_stoc_rhs = NULL; if (DDSIP_param->seccon) det_equ_rhs = (double *) DDSIP_Alloc(sizeof(double),DDSIP_param->seccon,"det_equ_rhs(DetEqu)"); else { fprintf (stderr,"XXX ERROR: no second stage contraints, got DDSIP_param->seccon=%d.\n",DDSIP_param->seccon); exit (1); } if (DDSIP_param->seccon - DDSIP_param->stocrhs>0) non_stoc_rhs = (double *) DDSIP_Alloc(sizeof(double),DDSIP_param->seccon - DDSIP_param->stocrhs,"non_stoc_rhs(DetEqu)"); fprintf (stderr, "\nBuilding deterministic equivalent. This may take some time.\nWorks only for expectation-based model so far.\n"); if (!(sense = (char *) calloc (DDSIP_param->seccon, sizeof (char)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); return; } if (!(obj_coef = (double *) calloc (DDSIP_param->firstvar + DDSIP_param->secvar, sizeof (double))) || !(scaled_obj_coef = (double *) calloc (DDSIP_bb->secvar, sizeof (double)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); return; } det_equ = CPXcloneprob (DDSIP_env, DDSIP_lp, &status); CPXchgprobname (DDSIP_env, det_equ, probname); if (!(rowname = (char **) calloc (DDSIP_param->seccon, sizeof (char *))) || !(scen_spec_rowname = (char **) calloc (DDSIP_param->seccon, sizeof (char *))) || !(rownamestore = (char *) calloc (DDSIP_param->seccon * 255, sizeof (char)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); return; } rowstorespace = DDSIP_param->seccon * 255; status = CPXgetrowname (DDSIP_env, DDSIP_lp, rowname, rownamestore, rowstorespace, &rowsurplus_p, DDSIP_param->firstcon, DDSIP_param->firstcon + DDSIP_param->seccon - 1); if (!(colname = (char **) calloc (DDSIP_param->firstvar + DDSIP_param->secvar, sizeof (char *))) || !(scen_spec_colname = (char **) calloc (DDSIP_param->secvar, sizeof (char *))) || !(colnamestore = (char *) calloc (DDSIP_param->secvar * 255, sizeof (char)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); return; } colstorespace = (DDSIP_param->firstvar + DDSIP_param->secvar) * 255; status = CPXgetcolname (DDSIP_env, DDSIP_lp, colname, colnamestore, colstorespace, &colsurplus_p, 0, DDSIP_param->firstvar + DDSIP_param->secvar - 1); /*____________________________________________________________________________________*/ status = CPXgetsense (DDSIP_env, DDSIP_lp, sense, DDSIP_param->firstcon, DDSIP_param->firstcon + DDSIP_param->seccon - 1); /*____________________________________________________________________________________*/ status = CPXgetrhs (DDSIP_env, DDSIP_lp, non_stoc_rhs, DDSIP_param->firstcon + DDSIP_param->stocrhs, DDSIP_param->firstcon + DDSIP_param->seccon - 1); /*____________________________________________________________________________________*/ status = CPXgetobj (DDSIP_env, DDSIP_lp, obj_coef, 0, DDSIP_param->firstvar + DDSIP_param->secvar - 1); /*____________________________________________________________________________________*/ //copy rownames scenario many times, append scenario index //and enter sense and rhs for (scen = 0; scen < DDSIP_param->scenarios; scen++) { for (j = 0; j < DDSIP_param->seccon; j++) { if (!(string2 = (char *) calloc (1, 255 * sizeof (char)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); return; } string1 = rowname[j]; sprintf (string2, "%sSC%.3d", string1, scen); scen_spec_rowname[j] = string2; if (j < DDSIP_param->stocrhs) det_equ_rhs[j] = DDSIP_data->rhs[DDSIP_param->stocrhs * scen + j]; else det_equ_rhs[j] = non_stoc_rhs[j - DDSIP_param->stocrhs]; } status = CPXnewrows (DDSIP_env, det_equ, DDSIP_param->seccon, det_equ_rhs, sense, NULL, scen_spec_rowname); for (j = 0; j < DDSIP_param->seccon; j++) DDSIP_Free ((void **) &(scen_spec_rowname[j])); } //copy colnames scenario many times, append scenario index //and enter into constraint matrix if (!(lb = (double *) calloc (DDSIP_param->firstvar + DDSIP_param->secvar, sizeof (double))) || !(lb_sorted = (double *) calloc (DDSIP_param->secvar, sizeof (double))) || !(ub = (double *) calloc (DDSIP_param->firstvar + DDSIP_param->secvar, sizeof (double))) || !(ub_sorted = (double *) calloc (DDSIP_param->secvar, sizeof (double))) || !(vartype = (char *) calloc (DDSIP_param->firstvar + DDSIP_param->secvar, sizeof (char))) || !(vartype_sorted = (char *) calloc (DDSIP_param->secvar, sizeof (double))) || !(colindex_revers = (int *) calloc (DDSIP_param->firstvar + DDSIP_param->secvar, sizeof (int))) || !(colindex_sorted = (int *) calloc (DDSIP_param->firstvar + DDSIP_param->secvar, sizeof (int)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); return; } status = CPXgetlb (DDSIP_env, det_equ, lb, 0, DDSIP_param->firstvar + DDSIP_param->secvar - 1); status = CPXgetub (DDSIP_env, det_equ, ub, 0, DDSIP_param->firstvar + DDSIP_param->secvar - 1); status = CPXgetctype (DDSIP_env, det_equ, vartype, 0, DDSIP_param->firstvar + DDSIP_param->secvar - 1); for (j = 0; j < DDSIP_param->secvar; j++) { vartype_sorted[j] = vartype[DDSIP_bb->secondindex[j]]; lb_sorted[j] = lb[DDSIP_bb->secondindex[j]]; ub_sorted[j] = ub[DDSIP_bb->secondindex[j]]; } for (scen = 0; scen < DDSIP_param->scenarios; scen++) { for (j = 0; j < DDSIP_param->secvar; j++) { if (!(string2 = (char *) calloc (1, 255 * sizeof (char)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); return; } string1 = colname[DDSIP_bb->secondindex[j]]; sprintf (string2, "%sSC%.3d", string1, scen); scen_spec_colname[j] = string2; scaled_obj_coef[j] = DDSIP_data->prob[scen] * obj_coef[DDSIP_bb->secondindex[j]]; } status = CPXnewcols (DDSIP_env, det_equ, DDSIP_param->secvar, scaled_obj_coef, lb_sorted, ub_sorted, vartype_sorted, scen_spec_colname); for (j = 0; j < DDSIP_param->secvar; j++) DDSIP_Free ((void **) &(scen_spec_colname[j])); } ///////////////////////////////////////////////// for (j = 0; j < DDSIP_param->firstvar; j++) { colindex_sorted[j] = DDSIP_bb->firstindex[j]; } for (j = 0; j < DDSIP_param->secvar; j++) { colindex_sorted[DDSIP_param->firstvar + j] = DDSIP_bb->secondindex[j]; } for (j = 0; j < DDSIP_param->firstvar + DDSIP_param->secvar; j++) { colindex_revers[colindex_sorted[j]] = j; } k = DDSIP_param->seccon / 60; printf ("\n0%% 100%%\n"); for (i = 0; i < DDSIP_param->seccon; i++) { for (j = 0; j < DDSIP_param->firstvar; j++) { if ((status = CPXgetcoef (DDSIP_env, det_equ, DDSIP_param->firstcon + i, colindex_sorted[j], &coef))) { fprintf (stderr, " Build det. equivalent: Error retrieving coefficient of first-stage Variable %d.\n", j); exit (1); } if (coef) { for (scen = 0; scen < DDSIP_param->scenarios; scen++) { status = CPXchgcoef (DDSIP_env, det_equ, DDSIP_param->firstcon + DDSIP_bb->seccon + scen * DDSIP_param->seccon + i, colindex_sorted[j], coef); if (status) { fprintf (stderr, " Build det. equivalent: Error setting coefficient of first-stage Variable %d.\n", j); exit (1); } } } } for (j = DDSIP_param->firstvar; j < DDSIP_param->firstvar + DDSIP_param->secvar; j++) { if ((status = CPXgetcoef (DDSIP_env, det_equ, DDSIP_param->firstcon + i, colindex_sorted[j], &coef))) { fprintf (stderr, " Build det. equivalent: Error retrieving coefficient of second-stage Variable %d.\n", j - DDSIP_param->firstvar); exit (1); } if (coef) { for (scen = 0; scen < DDSIP_param->scenarios; scen++) { status = CPXchgcoef (DDSIP_env, det_equ, DDSIP_param->firstcon + DDSIP_bb->seccon + scen * DDSIP_param->seccon + i, (scen + 1) * DDSIP_param->secvar + j, coef); } if (status) { fprintf (stderr, " Build det. equivalent: Error setting coefficient of second-stage Variable %d.\n", j - DDSIP_param->firstvar); exit (1); } } } if (!k) { for (j = 0; j <= 60 / DDSIP_param->seccon; j++) printf ("#"); } else if (i % k == k - 1) printf ("#"); } printf ("\n\n"); ///////delete original second stage rows & cols //////////////////////////////////////////// status = CPXdelrows (DDSIP_env, det_equ, DDSIP_param->firstcon, DDSIP_param->firstcon + DDSIP_bb->seccon - 1); j = 0; for (i = 0; i < DDSIP_param->secvar; i++) { status = CPXdelcols (DDSIP_env, det_equ, DDSIP_bb->secondindex[i] - j, DDSIP_bb->secondindex[i] - j); j++; } ///////enter stochastic matrix entries////////////////////////////////////////////////////// if (DDSIP_param->stocmat) { if (!(value = (double *) calloc (DDSIP_param->stocmat, sizeof (double))) || !(matcol_sorted = (int *) calloc (DDSIP_param->stocmat, sizeof (int)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); return; } for (j = 0; j < DDSIP_param->stocmat; j++) { matcol_sorted[j] = colindex_revers[DDSIP_data->matcol[j]]; } for (scen = 0; scen < DDSIP_param->scenarios; scen++) { for (j = 0; j < DDSIP_param->stocmat; j++) { value[j] = DDSIP_data->matval[scen * DDSIP_param->stocmat + j]; } status = CPXchgcoeflist (DDSIP_env, det_equ, DDSIP_param->stocmat, DDSIP_data->matrow, matcol_sorted, value); if (status) { char errmsg[1024]; CPXgeterrorstring (DDSIP_env, status, errmsg); fprintf (stderr, "in DetEqu: %s\n", errmsg); } for (j = 0; j < DDSIP_param->stocmat; j++) { DDSIP_data->matrow[j] += DDSIP_param->seccon; if (matcol_sorted[j] >= DDSIP_param->firstvar) matcol_sorted[j] += DDSIP_param->secvar; } } DDSIP_Free ((void **) &(value)); DDSIP_Free ((void **) &(matcol_sorted)); //set matrow to the old values for (j = 0; j < DDSIP_param->stocmat; j++) { DDSIP_data->matrow[j] -= DDSIP_param->scenarios * DDSIP_param->seccon; } } ///////enter stochastic cost coefficients ////////////////////////////////////////////////// if (DDSIP_param->stoccost) { if (!(value = (double *) calloc (DDSIP_param->stoccost, sizeof (double))) || !(matcol_sorted = (int *) calloc (DDSIP_param->stoccost, sizeof (int)))) { fprintf (stderr, "Not enough memory for building deterministic equivalent\n"); return; } for (j = 0; j < DDSIP_param->stoccost; j++) { value[j] = 0.0; matcol_sorted[j] = colindex_revers[DDSIP_data->costind[j]]; } for (scen = 0; scen < DDSIP_param->scenarios; scen++) { for (j = 0; j < DDSIP_param->stoccost; j++) { if (matcol_sorted[j] >= DDSIP_param->firstvar) value[j] = DDSIP_data->prob[scen] * DDSIP_data->cost[scen * DDSIP_param->stoccost + j]; else value[j] += DDSIP_data->prob[scen] * DDSIP_data->cost[scen * DDSIP_param->stoccost + j]; } status = CPXchgobj (DDSIP_env, det_equ, DDSIP_param->stoccost, matcol_sorted, value); if (status) { char errmsg[1024]; CPXgeterrorstring (DDSIP_env, status, errmsg); fprintf (stderr, "in DetEqu: %s\n", errmsg); } for (j = 0; j < DDSIP_param->stoccost; j++) { if (matcol_sorted[j] >= DDSIP_param->firstvar) matcol_sorted[j] += DDSIP_param->secvar; } } DDSIP_Free ((void **) &(value)); DDSIP_Free ((void **) &(matcol_sorted)); } //////////////////////////////////////////////////////////////////////////////////////////// status = CPXwriteprob (DDSIP_env, det_equ, probname, NULL); if (status) fprintf (DDSIP_outfile, " *** Deterministic equivalent not written successfully, status = %d\n", status); else fprintf (DDSIP_outfile, " *** Deterministic equivalent written successfully\n"); status = CPXfreeprob (DDSIP_env, &det_equ); DDSIP_Free ((void **) &(sense)); DDSIP_Free ((void **) &(vartype)); DDSIP_Free ((void **) &(rowname)); DDSIP_Free ((void **) &(rownamestore)); DDSIP_Free ((void **) &(colname)); DDSIP_Free ((void **) &(colnamestore)); DDSIP_Free ((void **) &(det_equ_rhs)); DDSIP_Free ((void **) &(non_stoc_rhs)); DDSIP_Free ((void **) &(lb)); DDSIP_Free ((void **) &(ub)); DDSIP_Free ((void **) &(vartype_sorted)); DDSIP_Free ((void **) &(lb_sorted)); DDSIP_Free ((void **) &(ub_sorted)); DDSIP_Free ((void **) &(obj_coef)); DDSIP_Free ((void **) &(scaled_obj_coef)); DDSIP_Free ((void **) &(colindex_sorted)); DDSIP_Free ((void **) &(colindex_revers)); DDSIP_Free ((void **) &(scen_spec_rowname)); DDSIP_Free ((void **) &(scen_spec_colname)); return; }
/* This function creates the following model: * Minimize * obj: x1 + x2 + x3 + x4 + x5 + x6 * Subject To * c1: x1 + x2 + x5 = 8 * c2: x3 + x5 + x6 = 10 * q1: [ -x1^2 + x2^2 + x3^2 ] <= 0 * q2: [ -x4^2 + x5^2 ] <= 0 * Bounds * x2 Free * x3 Free * x5 Free * End * which is a second order cone program in standard form. * The function returns a true value on success and false on error. * The function also sets up *cone_p as follows: * (*cone_p)[j] >= 0 Column j is contained in a cone constraint * and is the cone head variable of that * constraint. The index of the respective * quadratic constraint is given by (*cone_p)[j]. * (*cone_p)[j] = NOT_CONE_HEAD Column j is contained in a cone constraint * but is not the cone head variable of that * constraint. * (*cone_p)[j] = NOT_IN_CONE Column j is not contained in any cone * constraint. */ static int createmodel (CPXENVptr env, CPXLPptr lp, int **cone_p) { /* Column data. */ static double const obj[] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; static double const lb[] = { 0.0, -INF, -INF, 0.0, -INF, 0.0 }; static double const ub[] = { INF, INF, INF, INF, INF, INF }; static char const *const cname[] = { "x1", "x2", "x3", "x4", "x5", "x6" }; /* Row data. */ static double const rval[] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; static int const rind[] = { 0, 1, 4, 2, 4, 5 }; static int const rbeg[] = { 0, 3 }; static double const rhs[] = { 8.0, 10.0 }; static char const sense[] = { 'E', 'E' }; static char const *const rname[] = { "c1", "c2" }; /* Data for second order cone constraints. */ static double const qval[] = { -1.0, 1.0, 1.0 }; /* Same for all Q cons. */ static double const qrhs = 0.0; /* Same for all Q cons. */ static char const qsense = 'L'; /* Same for all Q cons. */ static int const qind1[] = { 0, 1, 2 }; static int const qind2[] = { 3, 4 }; int status; int ok = 0; int *cone = NULL; CPXCHANNELptr errc; /* Get the channel for printing error messages. */ if ( (status = CPXgetchannels (env, NULL, NULL, &errc, NULL)) != 0 ) goto TERMINATE; cone = malloc ((sizeof (obj) / sizeof (obj[0])) * sizeof (*cone)); if ( cone == NULL ) { CPXmsg (errc, "Out of memory!\n"); goto TERMINATE; } status = CPXchgobjsen (env, lp, CPX_MIN); if ( status != 0 ) goto TERMINATE; status = CPXnewcols (env, lp, sizeof (obj) / sizeof (obj[0]), obj, lb, ub, NULL, (char **)cname); if ( status != 0 ) goto TERMINATE; status = CPXaddrows (env, lp, 0, sizeof (rhs) / sizeof (rhs[0]), sizeof (rval) / sizeof (rval[0]), rhs, sense, rbeg, rind, rval, NULL, (char **)rname); if ( status != 0 ) goto TERMINATE; status = CPXaddqconstr (env, lp, 0, sizeof (qind1) / sizeof (qind1[0]), qrhs, qsense, NULL, NULL, qind1, qind1, qval, "q1"); if ( status != 0 ) goto TERMINATE; cone[0] = 0; cone[1] = NOT_CONE_HEAD; cone[2] = NOT_CONE_HEAD; status = CPXaddqconstr (env, lp, 0, sizeof (qind2) / sizeof (qind2[0]), qrhs, qsense, NULL, NULL, qind2, qind2, qval, "q2"); if ( status != 0 ) goto TERMINATE; cone[3] = 1; cone[4] = NOT_CONE_HEAD; cone[5] = NOT_IN_CONE; ok = 1; TERMINATE: if ( !ok ) free (cone); *cone_p = cone; return ok; }
int cg_solver(int m, MyRow* rows) { CPXENVptr env = NULL; CPXLPptr model = NULL; int status = 0; int error = 0; int i, j; int cur_numrows, cur_numcols; int n_cuts, cut; int solstat; double objval; double *x; double *z; int *cstat; int n0 = rows[0].n; int n1 = rows[0].n+m-1; /// One slack variable for constraint int h = (m-1)*n0 + m-1; /// Number of nonzeros double obj[n1]; double rhs[m-1]; /// The first row is for the cost vector char sense[m-1]; int jnd[h]; int ind[h]; double val[h]; int idx = 0; int* rmatbeg; int* rmatind; double* rmatval; double* b_bar; char* gc_sense; double* gc_rhs; /// Create environment env = CPXopenCPLEX (&status); if ( env == NULL ) { char errmsg[CPXMESSAGEBUFSIZE]; fprintf (stderr, "Could not open CPLEX environment. Status: %d\n", status); CPXgeterrorstring (env, status, errmsg); fprintf (stderr, "%s", errmsg); goto QUIT; } /// Disable presolve POST_CMD( CPXsetintparam (env, CPX_PARAM_PREIND, CPX_OFF) ); /// Create problem model = CPXcreateprob (env, &error, "gomory"); if (error) goto QUIT; /// Minimization problem POST_CMD( CPXchgobjsen (env, model, CPX_MIN) ); /// Add rows (remember first row is cost vector) for ( i = 0; i < m-1; ++i ) { sense[i]='E'; rhs[i] = rows[i+1].rhs; } POST_CMD( CPXnewrows(env, model, m-1, rhs, sense, NULL, NULL) ); /// Add problem variables for ( j = 0; j < n0; ++j ) obj[j] = rows[0].lhs[j]; /// Add slack variables for ( j = n0; j < n1; ++j ) obj[j] = 0; POST_CMD( CPXnewcols(env, model, n1, obj, NULL, NULL, NULL, NULL) ); /// Write the full matrix A into the LP (WARNING: should use only nonzeros entries) for ( i = 1; i < m; ++i ) { for ( j = 0; j < n0; ++j ) { jnd[idx] = i-1; ind[idx] = rows[i].ind[j]; val[idx] = rows[i].lhs[j]; idx++; } /// Add a slack variable per constraint jnd[idx] = i-1; ind[idx] = n0+i-1; val[idx] = 1.0; idx++; } POST_CMD( CPXchgcoeflist(env, model, idx, jnd, ind, val) ); /// Optimize the problem POST_CMD( CPXlpopt(env, model) ); /// Check the results cur_numrows = CPXgetnumrows (env, model); cur_numcols = CPXgetnumcols (env, model); x = (double *) malloc (cur_numcols * sizeof(double)); z = (double *) malloc (cur_numcols * sizeof(double)); cstat = (int *) malloc (cur_numcols * sizeof(int)); b_bar = (double *) malloc (cur_numrows * sizeof(double)); POST_CMD( CPXsolution (env, model, &solstat, &objval, x, NULL, NULL, NULL) ); if ( solstat != 1 ) { printf("The solver did not find an optimal solution\nSolver status code: %d\n",solstat); exit(0); } /// Write the output to the screen printf ("\nSolution status = %d\t\t", solstat); printf ("Solution value = %f\n\n", objval); /// If the solution is integer, is the optimum -> exit the loop if ( isInteger(cur_numcols, x) ) { fprintf(stdout,"The solution is already integer!\n"); goto QUIT; } /// Dump the problem model to 'gomory.lp' for debbuging POST_CMD( CPXwriteprob(env, model, "gomory.lp", NULL) ); /// Get the base statuses POST_CMD( CPXgetbase(env, model, cstat, NULL) ); print_solution(cur_numcols, x, cstat); printf("\nOptimal base inverted matrix:\n"); for ( i = 0; i < cur_numrows; ++i ) { b_bar[i] = 0; POST_CMD( CPXbinvrow(env, model, i, z) ); for ( j = 0; j < cur_numrows; ++j ) { printf("%.1f ", z[j]); b_bar[i] += z[j]*rhs[j]; } printf("\n"); } printf("\nOptimal solution (non basic variables are equal to zero):\n"); idx = 0; /// Compute the nonzeros n_cuts = 0; /// Number of fractional variables (cuts to be generated) for ( i = 0; i < m-1; ++i ) { POST_CMD( CPXbinvarow(env, model, i, z) ); for ( j = 0; j < n1; ++j ) { if ( z[j] >= 0 ) printf("+"); printf("%.1f x%d ", z[j], j+1); if ( floor(z[j]+0.5) != 0 ) idx++; } printf("= %.1f\n", b_bar[i]); /// Count the number of cuts to be generated if ( floor(b_bar[i]) != b_bar[i] ) n_cuts++; } /// Allocate memory for the new data structure gc_sense = (char*) malloc ( n_cuts * sizeof(char) ); gc_rhs = (double*) malloc ( n_cuts * sizeof(double) ); rmatbeg = (int*) malloc ( n_cuts * sizeof(int) ); rmatind = (int*) malloc ( idx * sizeof(int) ); rmatval = (double*) malloc ( idx * sizeof(double) ); printf("\nGenerate Gomory cuts:\n"); idx = 0; cut = 0; /// Index of cut to be added for ( i = 0; i < m-1; ++i ) if ( floor(b_bar[i]) != b_bar[i] ) { printf("Row %d gives cut -> ", i+1); POST_CMD( CPXbinvarow(env, model, i, z) ); rmatbeg[cut] = idx; for ( j = 0; j < n1; ++j ) { z[j] = floor(z[j]); /// DANGER! if ( z[j] != 0 ) { rmatind[idx] = j; rmatval[idx] = z[j]; idx++; } /// Print the cut if ( z[j] >= 0 ) printf("+"); printf("%.1f x%d ", z[j], j+1); } gc_rhs[cut] = floor(b_bar[i]); /// DANGER! gc_sense[cut] = 'L'; printf("<= %.1f\n", gc_rhs[cut]); cut++; } /// Add the new cuts POST_CMD( CPXaddrows (env, model, 0, n_cuts, idx, gc_rhs, gc_sense, rmatbeg, rmatind, rmatval, NULL, NULL) ); /// Solve the new LP POST_CMD( CPXlpopt(env, model) ); /// Check the results cur_numrows = CPXgetnumrows (env, model); cur_numcols = CPXgetnumcols (env, model); POST_CMD( CPXsolution (env, model, &solstat, &objval, x, NULL, NULL, NULL) ); if ( solstat != 1 ) { printf("The solver did not find an optimal solution\nSolver status code: %d\n",solstat); exit(0); } /// Write the output to the screen printf ("\nSolution status = %d\n", solstat); printf ("Solution value = %f\n\n", objval); POST_CMD( CPXgetbase(env, model, cstat, NULL) ); print_solution(cur_numcols, x, cstat); free_and_null ((char **) &x); free_and_null ((char **) &z); free_and_null ((char **) &cstat); free_and_null ((char **) &rmatbeg); free_and_null ((char **) &rmatind); free_and_null ((char **) &rmatval); QUIT: free_and_null ((char **) &x); free_and_null ((char **) &z); free_and_null ((char **) &cstat); if ( error ) { char errmsg[CPXMESSAGEBUFSIZE]; CPXgeterrorstring (env, error, errmsg); fprintf (stderr, "%s", errmsg); } /* Free up the problem as allocated by CPXcreateprob, if necessary */ if ( model != NULL ) { status = CPXfreeprob (env, &model); if ( status ) { fprintf (stderr, "CPXfreeprob failed, error code %d.\n", status); } } /* Free up the CPLEX environment, if necessary */ if ( env != NULL ) { status = CPXcloseCPLEX (&env); if ( error ) { char errmsg[CPXMESSAGEBUFSIZE]; fprintf (stderr, "Could not close CPLEX environment.\n"); CPXgeterrorstring (env, status, errmsg); fprintf (stderr, "%s", errmsg); } } return (status); }
static int populatebynonzero (CPXENVptr env, CPXLPptr lp) { int status = 0; double obj[NUMCOLS]; double lb[NUMCOLS]; double ub[NUMCOLS]; char *colname[NUMCOLS]; double rhs[NUMROWS]; char sense[NUMROWS]; char *rowname[NUMROWS]; int rowlist[NUMNZ]; int collist[NUMNZ]; double vallist[NUMNZ]; status = CPXchgobjsen (env, lp, CPX_MAX); /* Problem is maximization */ if ( status ) goto TERMINATE; /* Now create the new rows. First, populate the arrays. */ rowname[0] = "c1"; sense[0] = 'L'; rhs[0] = 20.0; rowname[1] = "c2"; sense[1] = 'L'; rhs[1] = 30.0; status = CPXnewrows (env, lp, NUMROWS, rhs, sense, NULL, rowname); if ( status ) goto TERMINATE; /* Now add the new columns. First, populate the arrays. */ obj[0] = 1.0; obj[1] = 2.0; obj[2] = 3.0; lb[0] = 0.0; lb[1] = 0.0; lb[2] = 0.0; ub[0] = 40.0; ub[1] = CPX_INFBOUND; ub[2] = CPX_INFBOUND; colname[0] = "x1"; colname[1] = "x2"; colname[2] = "x3"; status = CPXnewcols (env, lp, NUMCOLS, obj, lb, ub, NULL, colname); if ( status ) goto TERMINATE; /* Now create the list of coefficients */ rowlist[0] = 0; collist[0] = 0; vallist[0] = -1.0; rowlist[1] = 0; collist[1] = 1; vallist[1] = 1.0; rowlist[2] = 0; collist[2] = 2; vallist[2] = 1.0; rowlist[3] = 1; collist[3] = 0; vallist[3] = 1.0; rowlist[4] = 1; collist[4] = 1; vallist[4] = -3.0; rowlist[5] = 1; collist[5] = 2; vallist[5] = 1.0; status = CPXchgcoeflist (env, lp, 6, rowlist, collist, vallist); if ( status ) goto TERMINATE; TERMINATE: return (status); } /* END populatebynonzero */
static int buildmodel (CPXENVptr env, CPXLPptr lp) { int colcnt = NUMVARS*NUMMONTHS*NUMPRODUCTS; double *obj = NULL; double *lb = NULL; double *ub = NULL; char *ctype = NULL; int *rmatind = NULL; double *rmatval = NULL; int indicator; int rmatbeg[1]; double rhs[1]; char sense[1]; int m, p; int status = 0; status = CPXchgobjsen (env, lp, CPX_MAX); /* Maximization problem */ if ( status ) { fprintf (stderr, "Could not change objective sense.\n"); goto TERMINATE; } rmatbeg[0] = 0; /* Allocate colcnt-sized arrays */ obj = (double *) malloc (colcnt * sizeof(double)); lb = (double *) malloc (colcnt * sizeof(double)); ub = (double *) malloc (colcnt * sizeof(double)); ctype = (char *) malloc (colcnt * sizeof(char)); rmatind = (int * ) malloc (colcnt * sizeof(int)); rmatval = (double *) malloc (colcnt * sizeof(double)); if ( obj == NULL || lb == NULL || ub == NULL || ctype == NULL || rmatind == NULL || rmatval == NULL ) { fprintf (stderr, "Could not allocate colcnt arrays\n"); status = CPXERR_NO_MEMORY; goto TERMINATE; } /* Create variables. For each month and each product, we have 3 variables corresponding to the quantity used (semi-continuous), stored (continuous) and bought (continuous) and one binary variable indicating whether or not the product is used during this month. */ for (m = 0; m < NUMMONTHS; m++) { for (p = 0; p < NUMPRODUCTS; p++) { /* The quantity bought is a continuous variable. It has a cost */ obj[varindex(m, p, BUY)] = -cost[m*NUMPRODUCTS + p]; lb[varindex (m, p, BUY)] = 0.0; ub[varindex (m, p, BUY)] = CPX_INFBOUND; ctype[varindex (m, p, BUY)] = 'C'; /* When an oil is used, the quantity must be at least 20 tons. This is modeled as a semi-continuous variable. */ obj[varindex (m, p, USE)] = 0.0; lb[varindex (m, p, USE)] = 20.0; ub[varindex (m, p, USE)] = CPX_INFBOUND; ctype[varindex (m, p, USE)] = 'S'; /* It is possible to store up to 1000 tons of each product. There are storage costs. */ obj[varindex (m, p, STORE)] = -5.0; lb[varindex (m, p, STORE)] = 0.0; ub[varindex (m, p, STORE)] = 1000.0; ctype[varindex (m, p, STORE)] = 'C'; /* At the end, we must have exactly 500 tons of each product in storage. */ if ( m == NUMMONTHS - 1 ) { lb[varindex (m, p, STORE)] = 500.0; ub[varindex (m, p, STORE)] = 500.0; } /* The variable indicating whether or not a product is used during a month is a binary variable. */ obj[varindex (m, p, IS_USED)] = 0.0; lb[varindex (m, p, IS_USED)] = 0.0; ub[varindex (m, p, IS_USED)] = 1.0; ctype[varindex (m, p, IS_USED)] = 'B'; } } status = CPXnewcols (env, lp, colcnt, obj, lb, ub, ctype, NULL); if ( status ) { fprintf (stderr, "Could not add new columns.\n"); goto TERMINATE; } /* Constraints for each month */ for (m = 0; m < NUMMONTHS; m++) { int totalindex; /* For each product, create an indicator constraint linking the quantity used and the binary variable indicating whether or not the product is used */ for (p = 0; p < NUMPRODUCTS; p++) { indicator = varindex (m, p, IS_USED); rmatind[0] = varindex (m, p, USE); rmatval[0] = 1.0; status = CPXaddindconstr (env, lp, indicator, 1, 1, 0.0, 'L', rmatind, rmatval, NULL); if ( status ) { fprintf (stderr, "Could not add new indicator constraint.\n"); goto TERMINATE; } } /* Not more than 200 tons of vegetable oil can be refined */ rmatind[0] = varindex (m, VEGOIL1, USE); rmatind[1] = varindex (m, VEGOIL2, USE); rmatval[0] = 1.0; rmatval[1] = 1.0; rhs[0] = 200.0; sense[0] = 'L'; status = CPXaddrows (env, lp, 0, 1, 2, rhs, sense, rmatbeg, rmatind, rmatval, NULL, NULL); /* Not more than 250 tons of non-vegetable oil can be refined */ rmatind[0] = varindex (m, OIL1, USE); rmatind[1] = varindex (m, OIL2, USE); rmatind[2] = varindex (m, OIL3, USE); rmatval[0] = 1.0; rmatval[1] = 1.0; rmatval[2] = 1.0; rhs[0] = 250.0; sense[0] = 'L'; status = CPXaddrows (env, lp, 0, 1, 3, rhs, sense, rmatbeg, rmatind, rmatval, NULL, NULL); if ( status ) { fprintf (stderr, "Could not add new rows.\n"); goto TERMINATE; } /* Constraint on food composition */ /* Add a variable corresponding to total quantity produced in a month */ obj[0] = 150.0; lb[0] = 0.0; ub[0] = CPX_INFBOUND; ctype[0] = 'C'; status = CPXnewcols (env, lp, 1, obj, lb, ub, ctype, NULL); if ( status ) { fprintf (stderr, "Could not add new columns.\n"); goto TERMINATE; } totalindex = CPXgetnumcols (env, lp) - 1; /* Total quantity = sum (quantities) */ for (p = 0; p < NUMPRODUCTS; p++) { rmatind[p] = varindex (m, p, USE); rmatval[p] = 1.0; } rmatind[NUMPRODUCTS] = totalindex; rmatval[NUMPRODUCTS] = -1.0; rhs[0] = 0.0; sense[0] = 'E'; status = CPXaddrows (env, lp, 0, 1, NUMPRODUCTS + 1, rhs, sense, rmatbeg, rmatind, rmatval, NULL, NULL); if ( status ) { fprintf (stderr, "Could not add new rows.\n"); goto TERMINATE; } /* Hardness constraints sum (quantity * hardness) >= 3 * total quantity sum (quantity * hardness) <= 6 * total quantity */ for (p = 0; p < NUMPRODUCTS; p++) { rmatind[p] = varindex (m, p, USE); rmatval[p] = hardness[p]; } rmatind[NUMPRODUCTS] = totalindex; rmatval[NUMPRODUCTS] = -3.0; rhs[0] = 0.0; sense[0] = 'G'; status = CPXaddrows (env, lp, 0, 1, NUMPRODUCTS + 1, rhs, sense, rmatbeg, rmatind, rmatval, NULL, NULL); if ( status ) { fprintf (stderr, "Could not add new rows.\n"); goto TERMINATE; } rmatval[NUMPRODUCTS] = -6.0; sense[0] = 'L'; status = CPXaddrows (env, lp, 0, 1, NUMPRODUCTS + 1, rhs, sense, rmatbeg, rmatind, rmatval, NULL, NULL); if ( status ) { fprintf (stderr, "Could not add new rows.\n"); goto TERMINATE; } /* The food may never be made up of more than three oils */ for (p = 0; p < NUMPRODUCTS; p++) { rmatind[p] = varindex (m, p, IS_USED); rmatval[p] = 1.0; } rhs[0] = 3.0; sense[0] = 'L'; status = CPXaddrows (env, lp, 0, 1, NUMPRODUCTS, rhs, sense, rmatbeg, rmatind, rmatval, NULL, NULL); if ( status ) { fprintf (stderr, "Could not add new rows.\n"); goto TERMINATE; } /* If product veg 1 or veg 2 is used then oil 3 must be used */ indicator = varindex (m, VEGOIL1, IS_USED); rmatind[0] = varindex (m, OIL3, USE); rmatval[0] = 1.0; status = CPXaddindconstr (env, lp, indicator, 0, 1, 20.0, 'G', rmatind, rmatval, NULL); indicator = varindex (m, VEGOIL2, IS_USED); status = CPXaddindconstr (env, lp, indicator, 0, 1, 20.0, 'G', rmatind, rmatval, NULL); if ( status ) { fprintf (stderr, "Could not add new indicator constraint.\n"); goto TERMINATE; } /* We can store each product from one month to the next, starting with a stock of 500 tons */ for (p = 0; p < NUMPRODUCTS; p++) { int n = 0; if ( m != 0 ) { rmatind[n] = varindex (m-1, p, STORE); /* stored last month */ rmatval[n++] = 1.0; rmatind[n] = varindex (m, p, BUY); /* bought this month */ rmatval[n++] = 1.0; rmatind[n] = varindex (m, p, USE); /* used this month */ rmatval[n++] = -1.0; rmatind[n] = varindex (m, p, STORE); /* stored this month */ rmatval[n++] = -1.0; rhs[0] = 0.0; sense[0] = 'E'; } else { rmatind[n] = varindex (m, p, BUY); /* bought this month */ rmatval[n++] = 1.0; rmatind[n] = varindex (m, p, USE); /* used this month */ rmatval[n++] = -1.0; rmatind[n] = varindex (m, p, STORE); /* stored this month */ rmatval[n++] = -1.0; rhs[0] = -500.0; sense[0] = 'E'; } status = CPXaddrows (env, lp, 0, 1, n, rhs, sense, rmatbeg, rmatind, rmatval, NULL, NULL); if ( status ) { fprintf (stderr, "Could not add new rows.\n"); goto TERMINATE; } } } TERMINATE: free_and_null ((char **)&obj); free_and_null ((char **)&lb); free_and_null ((char **)&ub); free_and_null ((char **)&ctype); free_and_null ((char **)&rmatind); free_and_null ((char **)&rmatval); return (status); } /* END buildmodel */
int main(int argc, char **argv) { char ejes[100]; char labels[100]; char test[100]; archivoInput = argv[1]; randomness = argv[2]; porcentajeParticiones = atof(argv[3]); algoritmo = argv[4]; epsilonClique = atof(argv[5]); epsilonAgujero = atof(argv[6]); numeroDeModelo = atoi(argv[7]); RECORRIDO_ARBOL = atoi(argv[8]); VARIABLE_CORTE = atoi(argv[9]); semilla = atoi(argv[10]); srand(semilla); if(not freopen(archivoInput.c_str(), "r", stdin)){ cout << "No pude abrir archivo: " << archivoInput << endl; return 1; } sprintf(ejes, "ejes.out"); sprintf(labels, "labels.out"); if(randomness == "notrandom") { sprintf(test, "%s%s", argv[1], argv[2]); } else if (randomness == "random") { sprintf(test, "%s%s", argv[1], argv[3]); } else{ cout << "Paramtros mal introducidos" << endl; return 0; } read(randomness); // cada elemento de la particion conformado por un unico nodo // Le paso por parametro el algoritmo a implementar: bb = branch and bound, cb = cut and branch if(algoritmo != "bb" && algoritmo != "cb") { cout << "Error introduciendo parametro de algoritmo a ser aplicado " << endl; return 0; } // ============================================================================================== // Genero el problema de cplex. int status; // Creo el entorno. CPXENVptr env = CPXopenCPLEX(&status); // Puntero al entorno. CPXLPptr lp; // Puntero al LP if (env == NULL) { cerr << "Error creando el entorno" << endl; exit(1); } ///Iniciio el reloj CPXgettime(env, &inittime); // Creo el LP. lp = CPXcreateprob(env, &status, "instancia coloreo de grafo particionado"); if (lp == NULL) { cerr << "Error creando el LP" << endl; exit(1); } // Definimos las variables. En total, son P + N*P variables ( las W[j] y las X[i][j] ) int cantVariables = P + N*P; double *ub, *lb, *objfun; // Cota superior, cota inferior, coeficiente de la funcion objetivo. char *xctype, **colnames; // tipo de la variable , string con el nombre de la variable. ub = new double[cantVariables]; lb = new double[cantVariables]; objfun = new double[cantVariables]; xctype = new char[cantVariables]; colnames = new char*[cantVariables]; for (int i = 0; i < cantVariables; i++) { ub[i] = 1.0; // seteo upper y lower bounds de cada variable lb[i] = 0.0; if(i < P) { // agrego el costo en la funcion objetivo de cada variables objfun[i] = 1; // busco minimizar Sum(W_j) para j=0..P (la cantidad de colores utilizados). } else { objfun[i] = 0; // los X[i][j] no contribuyen a la funcion objetivo } xctype[i] = 'B'; // 'C' es continua, 'B' binaria, 'I' Entera. colnames[i] = new char[10]; } /* Defino el tipo de variable BoolVarMatrix, que sera utilizado en la resolucion * recordar: X_v_j = 1 sii el color j es asignado al vertice v * recordar: W_j = 1 si X_v_j = 1 para al menos un vertice v */ for(int j=0; j<P; j++) { sprintf(colnames[j], "W_%d", j); // cout << colnames[j] << endl; } for(int i=0; i<N; i++) { for(int j=0; j<P; j++) { sprintf(colnames[xijIndice(i,j)], "X_%d_%d", i, j); // cout << colnames[xijIndice(i,j)] << endl; } } // ========================== Agrego las columnas. =========================== // if(algoritmo == "cb"){ // si quiero resolver la relajacion, agregar los cortes y despues resolver el MIP, no agrego xctype status = CPXnewcols(env, lp, cantVariables, objfun, lb, ub, NULL, colnames); } else if (algoritmo == "bb"){ // si quiero hacer MIP, directamente, con brancha and bound, agrego xctype status = CPXnewcols(env, lp, cantVariables, objfun, lb, ub, xctype, colnames); } else { cout << "Error: parametro de algoritmo bb/cb mal introducido" << endl; return 0; } if (status) { cerr << "Problema agregando las variables CPXnewcols" << endl; exit(1); } // Libero las estructuras. for (int i = 0; i < cantVariables; i++) { delete[] colnames[i]; } delete[] ub; delete[] lb; delete[] objfun; delete[] xctype; delete[] colnames; // CPLEX por defecto minimiza. Le cambiamos el sentido a la funcion objetivo si se quiere maximizar. // CPXchgobjsen(env, lp, CPX_MAX); // ================================================================================================ // // ===================================== Restricciones ============================================ // // i) Asigno exactamente un color a exactamente un vertice de cada particion ( P restricciones ) // ii) Dos vertices adyacentes no pueden tener el mismo color ( E restricciones ) // iii) Los W_j estan bien armados, en funcion de X_v_j ( 2*P restricciones ) // ccnt = numero nuevo de columnas en las restricciones. // rcnt = cuantas restricciones se estan agregando. // nzcnt = # de coeficientes != 0 a ser agregados a la matriz. Solo se pasan los valores que no son cero. int ccnt = 0; int rcnt; if(numeroDeModelo == 0){ rcnt = P + (E*P)/2 + 2*P; // Cota maxima a la cantidad de restricciones } else{ rcnt = P + (E*P)/2 + N*P; } // (E/2 porque en la entrada se supone que en la entrada me pasan 2 veces cada eje) int nzcnt = 0; // al ppio es cero (para cada valor q agrego, lo voy a incrementar en 1) char sense[rcnt]; // Sentido de la desigualdad. 'G' es mayor o igual y 'E' para igualdad, 'L' menor o igual double *rhs = new double[rcnt]; // Termino independiente de las restricciones. int *matbeg = new int[rcnt]; //Posicion en la que comienza cada restriccion en matind y matval. int *matind = new int[rcnt*cantVariables]; // Array con los indices de las variables con coeficientes != 0 en la desigualdad. double *matval = new double[rcnt*cantVariables]; // Array que en la posicion i tiene coeficiente ( != 0) de la variable matind[i] en la restriccion. // CPLEX va a leer hasta la cantidad nzcnt que le pasemos. int cantRestricciones = 0; // r = numero de restriccion // i) P restricciones - exactamente un color a cada vertice (una restriccion por cada particion) for(int particion = 0; particion < P; particion++) { matbeg[cantRestricciones] = nzcnt; rhs[cantRestricciones] = 1; sense[cantRestricciones] = 'E'; for(int e = 0; e < S[particion].size(); e++) { for(int color = 0; color < P; color++) { matind[nzcnt] = xijIndice(S[particion][e], color); matval[nzcnt] = 1; nzcnt++; } } cantRestricciones++; } // ii) Cota superior de (E*P)/2 restricciones mas // Una para cada par de vecinos i j, para cada color pero solo cuando i < j, y estan en distinta particion for(int i = 0; i < N; i++) { for(int j = i + 1; j < N; j++) { if(M[i][j] == 1 and dameParticion(i) != dameParticion(j)){ for(int color = 0; color < P; color++) { matbeg[cantRestricciones] = nzcnt; rhs[cantRestricciones] = 1; sense[cantRestricciones] = 'L'; matind[nzcnt] = xijIndice(i,color); matval[nzcnt] = 1; nzcnt++; matind[nzcnt] = xijIndice(j,color); matval[nzcnt] = 1; nzcnt++; cantRestricciones++; } } } } if(numeroDeModelo == 0){ // iii) 2*P restricciones mas // - P * wj + sigma xij <= 0 for(int k=0; k<P; k++) { // para cada color matbeg[cantRestricciones] = nzcnt; rhs[cantRestricciones] = 0; sense[cantRestricciones] = 'L'; matind[nzcnt] = k; matval[nzcnt] = -1 * P; nzcnt++; for(int i=0; i<N; i++) { matind[nzcnt] = xijIndice(i,k); matval[nzcnt] = 1; nzcnt++; } cantRestricciones++; } // - wj + sigma xij >= 0 for(int k=0; k<P; k++) { matbeg[cantRestricciones] = nzcnt; rhs[cantRestricciones] = 0; sense[cantRestricciones] = 'G'; matind[nzcnt] = k; matval[nzcnt] = -1; nzcnt++; for(int i=0; i<N; i++) { matind[nzcnt] = xijIndice(i,k); matval[nzcnt] = 1; nzcnt++; } cantRestricciones++; } } else{ // iii) N*P restricciones mas // -wj + xij <= 0 for(int color = 0; color < P; color++) { for(int i = 0; i < N; i++) { matbeg[cantRestricciones] = nzcnt; rhs[cantRestricciones] = 0; sense[cantRestricciones] = 'L'; matind[nzcnt] = color; matval[nzcnt] = -1; nzcnt++; matind[nzcnt] = xijIndice(i, color); matval[nzcnt] = 1; nzcnt++; cantRestricciones++; } } } //Actualizo rcnt. rcnt = cantRestricciones; // =================================================================================================== // Agregamos las restricciones al lp. status = CPXaddrows(env, lp, ccnt, rcnt, nzcnt, rhs, sense, matbeg, matind, matval, NULL, NULL); if (status) { cerr << "Problema agregando restricciones." << endl; exit(1); } delete[] rhs; delete[] matbeg; delete[] matind; delete[] matval; // ============================================================================================== // // ================================== Optimizamos el problema. ================================== // // Seteo de algunos parametros. // Para desactivar la salida poner CPX_OFF. status = CPXsetintparam(env, CPX_PARAM_SCRIND, CPX_ON); if (status) { cerr << "Problema seteando SCRIND" << endl; exit(1); } // Setea el tiempo limite de ejecucion. status = CPXsetdblparam(env, CPX_PARAM_TILIM, TIEMPO_LIMITE); // setear limite de tiempo en 3600 !!!!!!! if (status) { cerr << "Problema seteando el tiempo limite" << endl; exit(1); } // Escribimos el problema a un archivo .lp. // status = CPXwriteprob(env, lp, "test.lp", NULL); if (status) { cerr << "Problema escribiendo modelo" << endl; exit(1); } // Seteamos algunos parametros para resolver con branch and bound CPXsetintparam(env, CPX_PARAM_MIPSEARCH, CPX_MIPSEARCH_TRADITIONAL); // Para facilitar la comparación evitamos paralelismo: CPXsetintparam(env, CPX_PARAM_THREADS, 1); //Para que no se adicionen planos de corte: CPXsetintparam(env,CPX_PARAM_EACHCUTLIM, 0); CPXsetintparam(env, CPX_PARAM_FRACCUTS, -1); CPXsetintparam(env, CPX_PARAM_LANDPCUTS, -1); // Para que no haga preprocesamientos CPXsetintparam(env, CPX_PARAM_PRESLVND, -1); CPXsetintparam(env, CPX_PARAM_REPEATPRESOLVE, 0); CPXsetintparam(env, CPX_PARAM_RELAXPREIND, 0); CPXsetintparam(env, CPX_PARAM_REDUCE, 0); // Recorrido del arbol CPXsetintparam(env, CPX_PARAM_NODESEL, RECORRIDO_ARBOL); // Seleccion de variable CPXsetintparam(env, CPX_PARAM_VARSEL, VARIABLE_CORTE); CPXgettime(env, &endtime); tiempoPreparar = endtime - inittime; inittime = endtime; // ========================================================================================================= // resuelvo con cut and branch (con los cortes definidos por nosotros) o con branch and bound (y sin cortes) // ========================================================================================================= if(algoritmo == "cb") { // while (algo) ... resolver el lp, chequear si la restr inducida por la clique actual es violada. Seguir //cout << "antes" << endl; for(int ciclocb=0; ciclocb<CANT_CICLOS_CB; ciclocb++) { status = CPXlpopt(env, lp); //cout << "despues" << endl; double objval; status = CPXgetobjval(env, lp, &objval); // Aca, deberia agregar los cortes requeridos, en funcion de "cliques" y "objval" // mostrameValores(env, lp); double *sol = new double[cantVariables]; CPXgetx(env, lp, sol, 0, cantVariables - 1); //CPXwriteprob (env, lp, "antesDeClique.lp", "LP"); // BUSCAR Y AGREGAR CLIQUE vector < vector<int> > agregados; for(int color=0; color<P; color++) { for(int i=0; i<CANT_RESTR_CLIQUES; i++) { bool iteracionRandom = (i!=0); vector<int> clique = dameClique(sol, color, iteracionRandom); sort(clique.begin(), clique.end()); bool incluido = find(agregados.begin(), agregados.end(), clique) != agregados.end(); if (not incluido and not clique.empty()) { agregados.push_back(clique); agregarRestriccionClique(env, lp, clique); cantidadCortesClique++; // cout << "AGREGO RESTRICCION DE CLIQUE de random " << iteracionRandom << " y de color #"<< color << ": "; // for(int j=0; j<clique.size(); j++) { // cout << clique[j] << " "; // } // cout << endl; } } } // BUSCAR Y AGREGAR AGUJERO agregados.clear(); for(int color=0; color<P; color++) { for(int i=0; i<CANT_RESTR_AGUJEROS; i++) { vector<int> agujero = dameAgujero(sol, color); bool incluido = find(agregados.begin(), agregados.end(), agujero) != agregados.end(); if (not incluido and not agujero.empty()) { agregados.push_back(agujero); agregarRestriccionAgujero(env, lp, agujero); cantidadCortesAgujero++; // cout << "AGREGO RESTRICCION DE AGUJERO de color #"<< color << ": "; // for(int j=0; j<agujero.size(); j++) { // cout << agujero[j] << " "; // } // cout << endl; } } } delete [] sol; } // CPXwriteprob (env, lp, "lpCB.lp", "LP"); ///Cuando salimos, pasamos a binaria y corremos un branch and bound char *ctype = new char[cantVariables]; for (int i = 0; i < cantVariables; i++) { ctype[i] = 'B'; } // cout << "Antes cambiar tipo" << endl; status = CPXcopyctype (env, lp, ctype); // cout << "Despues cambiar tipo" << endl; delete[] ctype; CPXgettime(env, &endtime); tiempoCutAndBranch = endtime - inittime; inittime = endtime; } ///Corremos el BB, ya sea porque esto es lo que queriamos originalemente, o porque terminamos con los planos de corte // cout << "ANTES" << endl; //CPXwriteprob (env, lp, "antesDeMip.lp", "LP"); CPXmipopt(env,lp); // cout << "DESPUES" << endl; CPXgettime(env, &endtime); tiempoBranchAndBound = endtime - inittime; // inittime = endtime; status = CPXgettime(env, &endtime); if (status) { cerr << "Problema optimizando CPLEX" << endl; exit(1); } // Chequeamos el estado de la solucion. int solstat; char statstring[510]; CPXCHARptr p; solstat = CPXgetstat(env, lp); p = CPXgetstatstring(env, solstat, statstring); string statstr(statstring); cout << endl << "Resultado de la optimizacion: " << statstring << endl; if(solstat!=CPXMIP_OPTIMAL && solstat!=CPXMIP_OPTIMAL_TOL && solstat!=CPXMIP_NODE_LIM_FEAS && solstat!=CPXMIP_TIME_LIM_FEAS){ cout << "No hay solucion" << endl; } else{ double objval; status = CPXgetobjval(env, lp, &objval); if (status) { cerr << "Problema obteniendo valor de mejor solucion." << endl; exit(1); } cout << "Datos de la resolucion: " << "\t" << objval << "\t" << tiempoPreparar + tiempoCutAndBranch + tiempoBranchAndBound << endl; cout << "Tiempo en preparar: " << "\t" << tiempoPreparar << endl; cout << "Tiempo en CB: " << "\t" << tiempoCutAndBranch << endl; cout << "Tiempo en BB: " << "\t" << tiempoBranchAndBound << endl; // Tomamos los valores de todas las variables. Estan numeradas de 0 a n-1. double *sol = new double[cantVariables]; status = CPXgetx(env, lp, sol, 0, cantVariables - 1); if (status) { cerr << "Problema obteniendo la solucion del LP." << endl; exit(1); } impresionModelo(env, lp); // Solo escribimos las variables distintas de cero (tolerancia, 1E-05). //solfile << "Status de la solucion: " << statstr << endl; // for(int j=0; j<P; j++) { // if(sol[j] > TOL) { // cout << "W_" << j << " = " << sol[j] << endl; // } // } // for(int i=0; i<N; i++) { // for(int j=0; j<P; j++) { // if(sol[P + P*i + j] > TOL) { // cout << "X_" << i << "_" << j << " = " << sol[P+P*i+j] << endl; // } // } // } //solfile.close(); // ==================== Devuelvo el grafo resultante coloreado, para graficar! ====================== // // ofstream streamEjes, streamLabels; //ofstream streamParticiones; // Tomamos los valores de la solucion y los escribimos a un archivo. // streamEjes.open(ejes); // for(int v1=0; v1<N; v1++) { // for(int v2=v1+1; v2<N; v2++) { // if (M[v1][v2] == 1) { // streamEjes << v1+1 << " " << v2+1 << endl; // } // } // } streamEjes.close(); // cout << ejes << endl; // streamLabels.open(labels); // bool estaColoreado; // for(int v=0; v<N; v++){ // estaColoreado = false; // for(int j=0; j<P; j++){ // if (sol[P + P*v + j] == 1) { // streamLabels << v+1 << " " << j+1 << endl; // estaColoreado = true; // } // } // if(not estaColoreado) { // streamLabels << v+1 << " " << 0 << endl; // } // } // streamLabels.close(); // delete [] sol; } return 0; }