int engine(int numassets, int numfactors, double *ub, double *lb, double *mu, double *sigma2, double *V, double *F, double lambda) { int retcode = 0; GRBenv *env = NULL; GRBmodel *model = NULL; int n, i, j, k; double *x; int *qrow, *qcol, Nq; double *qval; int *cind; double rhs; char sense; double *cval; int numnonz; char **names, bigname[100]; double expectedreturnval; printf("running solver engine\n"); n = numassets + numfactors; retcode = GRBloadenv(&env, "engine.log"); if (retcode) goto BACK; /* Create initial model */ retcode = GRBnewmodel(env, &model, "factors", n, NULL, NULL, NULL, NULL, NULL); if (retcode) goto BACK; names = (char **) calloc(n, sizeof(char *)); /** next we create the remaining attributes for the n columns **/ x = (double *) calloc (n, sizeof(double)); for(j = 0; j < numassets; j++){ names[j] = (char *)calloc(3, sizeof(char)); if(names[j] == NULL){ retcode = 1; goto BACK; } sprintf(names[j],"x%d", j); } for(j = numassets; j < numassets + numfactors; j++){ names[j] = (char *)calloc(3, sizeof(char)); if(names[j] == NULL){ retcode = 1; goto BACK; } sprintf(names[j],"F%d", j - numassets); } /* initialize variables */ for(j = 0; j < n; j++){ retcode = GRBsetstrattrelement(model, "VarName", j, names[j]); if (retcode) goto BACK; retcode = GRBsetdblattrelement(model, "Obj", j, -mu[j]); if (retcode) goto BACK; retcode = GRBsetdblattrelement(model, "LB", j, lb[j]); if (retcode) goto BACK; retcode = GRBsetdblattrelement(model, "UB", j, ub[j]); if (retcode) goto BACK; } /** next, the quadratic -- there are numassets + numfactors*numfactors nonzeroes: numassets residual variances plus the numfactors x numfactors factor covariance matrix**/ Nq = numassets + numfactors*numfactors; qrow = (int *) calloc(Nq, sizeof(int)); /** row indices **/ qcol = (int *) calloc(Nq, sizeof(int)); /** column indices **/ qval = (double *) calloc(Nq, sizeof(double)); /** values **/ if( ( qrow == NULL) || ( qcol == NULL) || (qval == NULL) ){ printf("could not create quadratic\n"); retcode = 1; goto BACK; } for (j = 0; j < numassets; j++){ qval[j] = lambda*sigma2[j]; qrow[j] = qcol[j] = j; } for (i = 0; i < numfactors; i++){ for (j = 0; j < numfactors; j++){ k = i*numfactors + j; qval[k + numassets] = lambda*F[k]; qrow[k + numassets] = numassets + i; qcol[k + numassets] = numassets + j; } } retcode = GRBaddqpterms(model, Nq, qrow, qcol, qval); if (retcode) goto BACK; /** now we will add one constraint at a time **/ /** we need to have a couple of auxiliary arrays **/ cind = (int *)calloc(n, sizeof(int)); /** n is over the top since no constraint is totally dense; but it's not too bad here **/ cval= (double *)calloc(n, sizeof(double)); if(!cval){ printf("cannot allocate cval\n"); retcode = 2; goto BACK; } for(i = 0; i < numfactors; i++){ for(j = 0; j < numassets; j++){ cval[j] = V[i*numassets + j]; cind[j] = j; } cind[numassets] = /* j */ numassets + i; cval[numassets] = -1; numnonz = numassets + 1; rhs = 0; sense = GRB_EQUAL; sprintf(bigname,"factor%d",i); retcode = GRBaddconstr(model, numnonz, cind, cval, sense, rhs, bigname); if (retcode) goto BACK; } /** sum of x variables = 1 **/ for (j = 0; j < numassets; j++){ cval[j] = 1.0; cind[j] = j; } numnonz = numassets; rhs = 1.0; sense = GRB_EQUAL; /* let's reuse some space */ sprintf(bigname, "sum"); retcode = GRBaddconstr(model, numnonz, cind, cval, sense, rhs, bigname); if (retcode) goto BACK; retcode = GRBupdatemodel(model); if (retcode) goto BACK; /** optional: write the problem **/ retcode = GRBwrite(model, "engine.lp"); if (retcode) goto BACK; retcode = GRBoptimize(model); if (retcode) goto BACK; /** get solution **/ retcode = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, n, x); if(retcode) goto BACK; /** now let's see the values **/ expectedreturnval = 0; for(j = 0; j < numassets; j++){ if( x[j] > 1.0e-09){ printf("%s = %g\n", names[j], x[j]); expectedreturnval += x[j]*mu[j]; } } printf("\n*** expected portfolio return: %g\n", expectedreturnval); GRBfreemodel(model); GRBfreeenv(env); BACK: printf("engine exits with code %d\n", retcode); return retcode; }
int main(int argc, char *argv[]) { GRBenv *env = NULL; GRBmodel *model = NULL; int error = 0, status; int s, w, col; int *cbeg = NULL; int *cind = NULL; int idx; double *cval = NULL; char *sense = NULL; char vname[MAXSTR]; double obj; int i, j, numvars, numconstrs; int *vbeg = NULL; int *vind = NULL; double *vval = NULL; double *vobj = NULL; double sol; char *cname, *sname; int varnamesct = 0; char **varnames = NULL; /* Sample data */ const int nShifts = 14; const int nWorkers = 7; /* Sets of days and workers */ char* Shifts[] = { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6", "Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13", "Sun14" }; char* Workers[] = { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" }; /* Number of workers required for each shift */ double shiftRequirements[] = { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 }; /* Amount each worker is paid to work one shift */ double pay[] = { 10, 12, 10, 8, 8, 9, 11 }; /* Worker availability: 0 if the worker is unavailable for a shift */ double availability[][14] = { { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 }, { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1 }, { 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1 }, { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; /* Create environment */ error = GRBloadenv(&env, "workforce3.log"); if (error || env == NULL) { fprintf(stderr, "Error: could not create environment\n"); exit(1); } /* Create initial model */ error = GRBnewmodel(env, &model, "workforce3", nWorkers * nShifts, NULL, NULL, NULL, NULL, NULL); if (error) goto QUIT; /* Initialize assignment decision variables: x[w][s] == 1 if worker w is assigned to shift s. Since an assignment model always produces integer solutions, we use continuous variables and solve as an LP. */ for (w = 0; w < nWorkers; ++w) { for (s = 0; s < nShifts; ++s) { col = xcol(w, s); sprintf(vname, "%s.%s", Workers[w], Shifts[s]); error = GRBsetdblattrelement(model, "UB", col, availability[w][s]); if (error) goto QUIT; error = GRBsetdblattrelement(model, "Obj", col, pay[w]); if (error) goto QUIT; error = GRBsetstrattrelement(model, "VarName", col, vname); if (error) goto QUIT; } } /* The objective is to minimize the total pay costs */ error = GRBsetintattr(model, "ModelSense", 1); if (error) goto QUIT; /* Make space for constraint data */ cbeg = malloc(sizeof(int) * nShifts); if (!cbeg) goto QUIT; cind = malloc(sizeof(int) * nShifts * nWorkers); if (!cind) goto QUIT; cval = malloc(sizeof(double) * nShifts * nWorkers); if (!cval) goto QUIT; sense = malloc(sizeof(char) * nShifts); if (!sense) goto QUIT; /* Constraint: assign exactly shiftRequirements[s] workers to each shift s */ idx = 0; for (s = 0; s < nShifts; ++s) { cbeg[s] = idx; sense[s] = GRB_EQUAL; for (w = 0; w < nWorkers; ++w) { cind[idx] = xcol(w, s); cval[idx++] = 1.0; } } error = GRBaddconstrs(model, nShifts, idx, cbeg, cind, cval, sense, shiftRequirements, Shifts); if (error) goto QUIT; /* Optimize */ error = GRBoptimize(model); if (error) goto QUIT; error = GRBgetintattr(model, "Status", &status); if (error) goto QUIT; if (status == GRB_UNBOUNDED) { printf("The model cannot be solved because it is unbounded\n"); goto QUIT; } if (status == GRB_OPTIMAL) { error = GRBgetdblattr(model, "ObjVal", &obj); if (error) goto QUIT; printf("The optimal objective is %f\n", obj); goto QUIT; } if ((status != GRB_INF_OR_UNBD) && (status != GRB_INFEASIBLE)) { printf("Optimization was stopped with status %i\n", status); goto QUIT; } /* Add slack variables to make the model feasible */ printf("The model is infeasible; adding slack variables\n"); /* Determine the matrix size before adding the slacks */ error = GRBgetintattr(model, "NumVars", &numvars); if (error) goto QUIT; error = GRBgetintattr(model, "NumConstrs", &numconstrs); if (error) goto QUIT; /* Set original objective coefficients to zero */ for (j = 0; j < numvars; ++j) { error = GRBsetdblattrelement(model, "Obj", j, 0.0); if (error) goto QUIT; } /* Add a new slack variable to each shift constraint so that the shifts can be satisfied */ vbeg = malloc(sizeof(int) * numconstrs); if (!vbeg) goto QUIT; vind = malloc(sizeof(int) * numconstrs); if (!vind) goto QUIT; vval = malloc(sizeof(double) * numconstrs); if (!vval) goto QUIT; vobj = malloc(sizeof(double) * numconstrs); if (!vobj) goto QUIT; varnames = calloc(numconstrs, sizeof(char*)); if (!varnames) goto QUIT; for (i = 0; i < numconstrs; ++i) { vbeg[i] = i; vind[i] = i; vval[i] = 1.0; vobj[i] = 1.0; error = GRBgetstrattrelement(model, "ConstrName", i, &cname); if (error) goto QUIT; varnames[i] = malloc(sizeof(char*) * (6 + strlen(cname))); if (!varnames[i]) goto QUIT; varnamesct++; strcpy(varnames[i], cname); strcat(varnames[i], "Slack"); } error = GRBaddvars(model, numconstrs, numconstrs, vbeg, vind, vval, vobj, NULL, NULL, NULL, varnames); if (error) goto QUIT; error = GRBupdatemodel(model); if (error) goto QUIT; /* Solve the model with slacks */ error = GRBoptimize(model); if (error) goto QUIT; error = GRBgetintattr(model, "Status", &status); if (error) goto QUIT; if ((status == GRB_INF_OR_UNBD) || (status == GRB_INFEASIBLE) || (status == GRB_UNBOUNDED)) { printf("The model with slacks cannot be solved " "because it is infeasible or unbounded\n"); goto QUIT; } if (status != GRB_OPTIMAL) { printf("Optimization was stopped with status %i\n", status); goto QUIT; } printf("\nSlack values:\n"); for (j = numvars; j < numvars + numconstrs; ++j) { error = GRBgetdblattrelement(model, "X", j, &sol); if (error) goto QUIT; if (sol > 1e-6) { error = GRBgetstrattrelement(model, "VarName", j, &sname); if (error) goto QUIT; printf("%s = %f\n", sname, sol); } } QUIT: /* Error reporting */ if (error) { printf("ERROR: %s\n", GRBgeterrormsg(env)); exit(1); } /* Free data */ free(cbeg); free(cind); free(cval); free(sense); free(vbeg); free(vind); free(vval); free(vobj); for (i = 0; i < varnamesct; ++i) { free(varnames[i]); } free(varnames); /* Free model */ GRBfreemodel(model); /* Free environment */ GRBfreeenv(env); return 0; }
int main(int argc, char *argv[]) { GRBenv *env = NULL; GRBmodel *model = NULL; int error = 0, status; int s, w, col; int *cbeg = NULL; int *cind = NULL; int idx; double *cval = NULL; char *sense = NULL; char vname[MAXSTR]; double obj; int i, iis, numconstrs; char *cname; /* Sample data */ const int nShifts = 14; const int nWorkers = 7; /* Sets of days and workers */ char* Shifts[] = { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6", "Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13", "Sun14" }; char* Workers[] = { "Amy", "Bob", "Cathy", "Dan", "Ed", "Fred", "Gu" }; /* Number of workers required for each shift */ double shiftRequirements[] = { 3, 2, 4, 4, 5, 6, 5, 2, 2, 3, 4, 6, 7, 5 }; /* Amount each worker is paid to work one shift */ double pay[] = { 10, 12, 10, 8, 8, 9, 11 }; /* Worker availability: 0 if the worker is unavailable for a shift */ double availability[][14] = { { 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 }, { 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0 }, { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 }, { 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1 }, { 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1 }, { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; /* Create environment */ error = GRBloadenv(&env, "workforce1.log"); if (error || env == NULL) { fprintf(stderr, "Error: could not create environment\n"); exit(1); } /* Create initial model */ error = GRBnewmodel(env, &model, "workforce1", nWorkers * nShifts, NULL, NULL, NULL, NULL, NULL); if (error) goto QUIT; /* Initialize assignment decision variables: x[w][s] == 1 if worker w is assigned to shift s. Since an assignment model always produces integer solutions, we use continuous variables and solve as an LP. */ for (w = 0; w < nWorkers; ++w) { for (s = 0; s < nShifts; ++s) { col = xcol(w, s); sprintf(vname, "%s.%s", Workers[w], Shifts[s]); error = GRBsetdblattrelement(model, "UB", col, availability[w][s]); if (error) goto QUIT; error = GRBsetdblattrelement(model, "Obj", col, pay[w]); if (error) goto QUIT; error = GRBsetstrattrelement(model, "VarName", col, vname); if (error) goto QUIT; } } /* The objective is to minimize the total pay costs */ error = GRBsetintattr(model, "ModelSense", 1); if (error) goto QUIT; /* Make space for constraint data */ cbeg = malloc(sizeof(int) * nShifts); if (!cbeg) goto QUIT; cind = malloc(sizeof(int) * nShifts * nWorkers); if (!cind) goto QUIT; cval = malloc(sizeof(double) * nShifts * nWorkers); if (!cval) goto QUIT; sense = malloc(sizeof(char) * nShifts); if (!sense) goto QUIT; /* Constraint: assign exactly shiftRequirements[s] workers to each shift s */ idx = 0; for (s = 0; s < nShifts; ++s) { cbeg[s] = idx; sense[s] = GRB_EQUAL; for (w = 0; w < nWorkers; ++w) { cind[idx] = xcol(w, s); cval[idx++] = 1.0; } } error = GRBaddconstrs(model, nShifts, idx, cbeg, cind, cval, sense, shiftRequirements, Shifts); if (error) goto QUIT; /* Optimize */ error = GRBoptimize(model); if (error) goto QUIT; error = GRBgetintattr(model, "Status", &status); if (error) goto QUIT; if (status == GRB_UNBOUNDED) { printf("The model cannot be solved because it is unbounded\n"); goto QUIT; } if (status == GRB_OPTIMAL) { error = GRBgetdblattr(model, "ObjVal", &obj); if (error) goto QUIT; printf("The optimal objective is %f\n", obj); goto QUIT; } if ((status != GRB_INF_OR_UNBD) && (status != GRB_INFEASIBLE)) { printf("Optimization was stopped with status %i\n", status); goto QUIT; } /* do IIS */ printf("The model is infeasible; computing IIS\n"); error = GRBcomputeIIS(model); if (error) goto QUIT; printf("\nThe following constraint(s) cannot be satisfied:\n"); error = GRBgetintattr(model, "NumConstrs", &numconstrs); if (error) goto QUIT; for (i = 0; i < numconstrs; ++i) { error = GRBgetintattrelement(model, "IISConstr", i, &iis); if (error) goto QUIT; if (iis) { error = GRBgetstrattrelement(model, "ConstrName", i, &cname); if (error) goto QUIT; printf("%s\n", cname); } } QUIT: /* Error reporting */ if (error) { printf("ERROR: %s\n", GRBgeterrormsg(env)); exit(1); } /* Free data */ free(cbeg); free(cind); free(cval); free(sense); /* Free model */ GRBfreemodel(model); /* Free environment */ GRBfreeenv(env); return 0; }
int main(void) { int retcode = 0; GRBenv *env = NULL; GRBmodel *model = NULL; int n, j; double *obj = NULL; double *lb = NULL; double *ub = NULL; double *x; int *qrow, *qcol, Nq; double *qval; int *cind; double rhs; char sense; double *cval; int numnonz; char **names; n = 9; /** 7 'x' variables, 2 factor variables **/ retcode = GRBloadenv(&env, "factormodel.log"); if (retcode) goto BACK; /* Create initial model */ retcode = GRBnewmodel(env, &model, "second", n, NULL, NULL, NULL, NULL, NULL); if (retcode) goto BACK; names = (char **) calloc(n, sizeof(char *)); /** next we create the remaining attributes for the n columns **/ obj = (double *) calloc (n, sizeof(double)); ub = (double *) calloc (n, sizeof(double)); lb = (double *) calloc (n, sizeof(double)); x = (double *) calloc (n, sizeof(double)); for(j = 0; j < 7; j++){ names[j] = (char *)calloc(3, sizeof(char)); if(names[j] == NULL){ retcode = 1; goto BACK; } sprintf(names[j],"x%d", j); } for(j = 7; j < 9; j++){ names[j] = (char *)calloc(3, sizeof(char)); if(names[j] == NULL){ retcode = 1; goto BACK; } sprintf(names[j],"y%d", j - 7); } obj[0] = -.233; obj[1] = -3.422; obj[2] = -.1904; obj[3] = -.5411; obj[4] = -.045; obj[5] = -1.271; obj[6] = -0.955; /** calloc initializes memory to zero, so all other obj[j] are zero **/ /**next, the upper bounds on the x variables **/ ub[0] = 0.6; ub[1] = 0.8; ub[2] = 0.8; ub[3] = 0.5; ub[4] = 0.5; ub[5] = 0.26; ub[6] = 0.99; /** the upper bounds on the two factor variables -- we make them large **/ ub[7] = 100; ub[8] = 100; /** the lower bounds on the factor variables **/ lb[7] = -100; lb[8] = -100; /* initialize variables */ for(j = 0; j < n; j++){ retcode = GRBsetstrattrelement(model, "VarName", j, names[j]); if (retcode) goto BACK; retcode = GRBsetdblattrelement(model, "Obj", j, obj[j]); if (retcode) goto BACK; retcode = GRBsetdblattrelement(model, "LB", j, lb[j]); if (retcode) goto BACK; retcode = GRBsetdblattrelement(model, "UB", j, ub[j]); if (retcode) goto BACK; } /** next, the quadratic -- there are 11 nonzeroes: 7 residual variances plus the 2x2 factor covariance matrix**/ Nq = 11; qrow = (int *) calloc(Nq, sizeof(int)); /** row indices **/ qcol = (int *) calloc(Nq, sizeof(int)); /** column indices **/ qval = (double *) calloc(Nq, sizeof(double)); /** values **/ if( ( qrow == NULL) || ( qcol == NULL) || (qval == NULL) ){ printf("could not create quadratic\n"); retcode = 1; goto BACK; } qval[0] = 10.0; qrow[0] = 0; qcol[0] = 0; qval[1] = 20.0; qrow[1] = 1; qcol[1] = 1; qval[2] = 30.0; qrow[2] = 2; qcol[2] = 2; qval[3] = 40.0; qrow[3] = 3; qcol[3] = 3; qval[4] = 50.0; qrow[4] = 4; qcol[4] = 4; qval[5] = 60.0; qrow[5] = 5; qcol[5] = 5; qval[6] = 70.0; qrow[6] = 6; qcol[6] = 6; qval[7] = 100.0; qrow[7] = 7; qcol[7] = 7; qval[8] = 200.0; qrow[8] = 8; qcol[8] = 8; qval[9] = 0.1; qrow[9] = 7; qcol[9] = 8; qval[10] = 0.1; qrow[10] = 8; qcol[10] = 7; retcode = GRBaddqpterms(model, 11, qrow, qcol, qval); if (retcode) goto BACK; /** now we will add one constraint at a time **/ /** we need to have a couple of auxiliary arrays **/ cind = (int *)calloc(n, sizeof(int)); /** n is over the top since no constraint is totally dense; but it's not too bad here **/ cval= (double *)calloc(n, sizeof(double)); /** two factor constraints, first one is next**/ cval[0] = 1.508; cval[1] = .7802; cval[2] = 1.8796; cval[3] = 4.256; cval[4] = 1.335; cval[5] = 2.026; cval[6] = 1.909; cval[7] = -1; for(j = 0; j < 7; j++) cind[j] = j; cind[7] = 7; numnonz = 8; rhs = 0; sense = GRB_EQUAL; retcode = GRBaddconstr(model, numnonz, cind, cval, sense, rhs, "first_constraint"); if (retcode) goto BACK; /** second factor constraint **/ cval[0] = 4.228; cval[1] = 1.2945; cval[2] = .827; cval[3] = 2.149; cval[4] = 2.353; cval[5] = 0.3026; cval[6] = 1.487; cval[7] = -1; for(j = 0; j < 7; j++) cind[j] = j; /** redundant! but let's keep it here so that we know it will be used **/ cind[7] = 7; numnonz = 8; rhs = 0; sense = GRB_EQUAL; retcode = GRBaddconstr(model, numnonz, cind, cval, sense, rhs, "second_constraint"); if (retcode) goto BACK; /** sum of x variables = 1 **/ cval[0] = 1.0; cval[1] = 1.0; cval[2] = 1.0; cval[3] = 1.0; cval[4] = 1.0; cval[5] = 1.0; cval[6] = 1.0; for(j = 0; j < 7; j++) cind[j] = j; numnonz = 7; rhs = 1.0; sense = GRB_EQUAL; retcode = GRBaddconstr(model, numnonz, cind, cval, sense, rhs, "convexity"); if (retcode) goto BACK; retcode = GRBupdatemodel(model); if (retcode) goto BACK; /** optional: write the problem **/ retcode = GRBwrite(model, "factorqp.lp"); if (retcode) goto BACK; retcode = GRBoptimize(model); if (retcode) goto BACK; /** get solution **/ retcode = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, n, x); if(retcode) goto BACK; /** now let's see the values **/ for(j = 0; j < n; j++){ printf("%s = %g\n", names[j], x[j]); } GRBfreemodel(model); GRBfreeenv(env); BACK: printf("\nexiting with retcode %d\n", retcode); return retcode; }