int main(int argc, char *argv[])
{
	GRBEnv* env = 0;
	GRBVar* covered = 0; // we want to maximize demand covered
	GRBVar* facility = 0;
	int max_n_Facilities = 10;

	try
	{
		const string filename = "/Users/katarzyna/Dropbox/matlab/2015-05 PKITS/aij_matrix.txt";

		std::vector<std::vector<long int> > aij_matrix;
		readMatrix_aij(filename, aij_matrix);

		std::cout << "matrix size "<< aij_matrix.size() <<" x "<< aij_matrix[0].size() << std::endl;

		// Model
		env = new GRBEnv();
		GRBModel model = GRBModel(*env);
		model.set(GRB_StringAttr_ModelName, "minimize number of facilities");

		// Demand coverage decision variable, covered[i] == 1 if demand is covered
		covered = model.addVars(aij_matrix.size(), GRB_BINARY);
		model.update();

		// Facility open variables: facility[j] == 1 if facility j is open.
		facility = model.addVars(aij_matrix.size(), GRB_BINARY);
		model.update();


		// Set the objective to maximize the demand covered
		for (unsigned int i = 0; i < aij_matrix.size(); ++i)
		{
			ostringstream vname;
			vname << "Demand " << i;
			covered[i].set(GRB_DoubleAttr_Obj, 1);
			covered[i].set(GRB_StringAttr_VarName, vname.str());
		}

		for (unsigned int i = 0; i < aij_matrix.size(); ++i)
		{
			ostringstream vname;
			vname << "Open " << i;
			facility[i].set(GRB_DoubleAttr_Obj, 0);
			facility[i].set(GRB_StringAttr_VarName, vname.str());
		}

		// The objective is to maximize the total demand covered
		model.set(GRB_IntAttr_ModelSense, 0);

		// Update model
		model.update();

		// Constraints

		// If demand i is covered by at least one station, then covered[i] == 1
		for (unsigned int i = 0; i < aij_matrix.size(); ++i)
		{
			GRBLinExpr demand_is_covered = 0;
			for (unsigned int j = 0; j < aij_matrix.size(); ++j)
			{
				demand_is_covered += aij_matrix[i][j] * facility[j];
			}
			ostringstream cname;
			cname << "Demand_i_is_covered " << i;
			model.addConstr(demand_is_covered >= covered[i], cname.str());
		}

		// We allow no more than n facilities
		GRBLinExpr facilities_to_open = 0;
		for (unsigned int j = 0; j < aij_matrix.size(); ++j) {
			facilities_to_open += facility[j];
		}

		ostringstream vname;
		vname << "Max facility... ";
		model.addConstr(facilities_to_open <= max_n_Facilities);

		model.update();

		// Solve
		model.optimize();

		model.write("/Users/katarzyna/Dropbox/matlab/2015-05 PKITS/output.lp");

		// Print solution
		cout << "\nTOTAL COSTS: " << model.get(GRB_DoubleAttr_ObjVal) << endl;
		cout << "SOLUTION:" << endl;
		int sum_d = 0;
		for (unsigned int i = 0; i < aij_matrix.size(); ++i)
		{
			if (covered[i].get(GRB_DoubleAttr_X) == 1.0)
			{
				//cout << "Demand " << i << " covered." << endl;
				sum_d += 1;
			}
		}

		int sum_f = 0;
		for (unsigned int i = 0; i < aij_matrix.size(); ++i)
		{
			if (facility[i].get(GRB_DoubleAttr_X) == 1.0)
			{
				cout << "Facility " << i << " is opened." << endl;
				sum_f += 1;
			}
		}
		cout << sum_f << " facilities is open." << endl;
		cout << sum_d << " customers is covered." << endl;


	} catch (GRBException e)
	{
		cout << "Error code = " << e.getErrorCode() << endl;
		cout << e.getMessage() << endl;
	} catch (...)
	{
		cout << "Exception during optimization" << endl;
	}
}
Beispiel #2
0
int
main(int   argc,
     char *argv[])
{
  if (argc < 2) {
    cout << "Usage: tsp_c++ filename" << endl;
    return 1;
  }

  int n = atoi(argv[1]);
  double* x = new double[n];
  double* y = new double[n];

  for (int i = 0; i < n; i++) {
    x[i] = ((double) rand())/RAND_MAX;
    y[i] = ((double) rand())/RAND_MAX;
  }

  GRBEnv *env = NULL;
  GRBVar **vars = new GRBVar*[n];

  try {
    int i, j;

    env = new GRBEnv();
    GRBModel model = GRBModel(*env);

    // Must disable dual reductions when using lazy constraints

    model.getEnv().set(GRB_IntParam_DualReductions, 0);

    // Create binary decision variables

    for (i = 0; i < n; i++)
      vars[i] = model.addVars(n);
    model.update();

    for (i = 0; i < n; i++) {
      for (j = 0; j < n; j++) {
        vars[i][j].set(GRB_CharAttr_VType, GRB_BINARY);
        vars[i][j].set(GRB_DoubleAttr_Obj, distance(x, y, i, j));
        vars[i][j].set(GRB_StringAttr_VarName, "x_"+itos(i)+"_"+itos(j));
      }
    }

    // Integrate new variables

    model.update();

    // Degree-2 constraints

    for (i = 0; i < n; i++) {
      GRBLinExpr expr = 0;
      for (j = 0; j < n; j++)
        expr += vars[i][j];
      model.addConstr(expr == 2, "deg2_"+itos(i));
    }

    // Forbid edge from node back to itself

    for (i = 0; i < n; i++)
      vars[i][i].set(GRB_DoubleAttr_UB, 0);

    // Symmetric TSP

    for (i = 0; i < n; i++)
      for (j = 0; j < i; j++)
        model.addConstr(vars[i][j] == vars[j][i]);

    // Set callback function

    subtourelim cb = subtourelim(vars, n);
    model.setCallback(&cb);

    // Optimize model

    model.optimize();

    // Extract solution

    if (model.get(GRB_IntAttr_SolCount) > 0) {
      double **sol = new double*[n];
      for (i = 0; i < n; i++)
        sol[i] = model.get(GRB_DoubleAttr_X, vars[i], n);

      int* tour = new int[n];
      int len;

      findsubtour(n, sol, &len, tour);

      cout << "Tour: ";
      for (i = 0; i < len; i++)
        cout << tour[i] << " ";
      cout << endl;

      for (i = 0; i < n; i++)
        delete[] sol[i];
      delete[] sol;
      delete[] tour;
    }

  } catch (GRBException e) {
    cout << "Error number: " << e.getErrorCode() << endl;
    cout << e.getMessage() << endl;
  } catch (...) {
    cout << "Error during optimization" << endl;
  }

  for (int i = 0; i < n; i++)
    delete[] vars[i];
  delete[] vars;
  delete[] x;
  delete[] y;
  delete env;
  return 0;
}
Beispiel #3
0
int
main(int argc,
     char *argv[])
{
  GRBEnv* env = 0;
  GRBConstr* c = 0;
  GRBVar* v = 0;
  GRBVar** x = 0;
  GRBVar* slacks = 0;
  GRBVar* totShifts = 0;
  GRBVar* diffShifts = 0;
  int xCt = 0;
  try
  {

    // Sample data
    const int nShifts = 14;
    const int nWorkers = 7;

    // Sets of days and workers
    string Shifts[] =
      { "Mon1", "Tue2", "Wed3", "Thu4", "Fri5", "Sat6",
        "Sun7", "Mon8", "Tue9", "Wed10", "Thu11", "Fri12", "Sat13",
        "Sun14" };
    string 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 };

    // Worker availability: 0 if the worker is unavailable for a shift
    double availability[][nShifts] =
      { { 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 } };

    // Model
    env = new GRBEnv();
    GRBModel model = GRBModel(*env);
    model.set(GRB_StringAttr_ModelName, "assignment");

    // Assignment variables: x[w][s] == 1 if worker w is assigned
    // to shift s. This is no longer a pure assignment model, so we must
    // use binary variables.
    x = new GRBVar*[nWorkers];
    for (int w = 0; w < nWorkers; ++w)
    {
      x[w] = model.addVars(nShifts);
      xCt++;
      model.update();
      for (int s = 0; s < nShifts; ++s)
      {
        ostringstream vname;
        vname << Workers[w] << "." << Shifts[s];
        x[w][s].set(GRB_DoubleAttr_UB, availability[w][s]);
        x[w][s].set(GRB_CharAttr_VType, GRB_BINARY);
        x[w][s].set(GRB_StringAttr_VarName, vname.str());
      }
    }

    // Slack variables for each shift constraint so that the shifts can
    // be satisfied
    slacks = model.addVars(nShifts);
    model.update();
    for (int s = 0; s < nShifts; ++s)
    {
      ostringstream vname;
      vname << Shifts[s] << "Slack";
      slacks[s].set(GRB_StringAttr_VarName, vname.str());
    }

    // Variable to represent the total slack
    GRBVar totSlack = model.addVar(0, GRB_INFINITY, 0, GRB_CONTINUOUS,
                                   "totSlack");

    // Variables to count the total shifts worked by each worker
    totShifts = model.addVars(nWorkers);
    model.update();
    for (int w = 0; w < nWorkers; ++w)
    {
      ostringstream vname;
      vname << Workers[w] << "TotShifts";
      totShifts[w].set(GRB_StringAttr_VarName, vname.str());
    }

    // Update model to integrate new variables
    model.update();

    GRBLinExpr lhs;

    // Constraint: assign exactly shiftRequirements[s] workers
    // to each shift s
    for (int s = 0; s < nShifts; ++s)
    {
      lhs = 0;
      lhs += slacks[s];
      for (int w = 0; w < nWorkers; ++w)
      {
        lhs += x[w][s];
      }
      model.addConstr(lhs == shiftRequirements[s], Shifts[s]);
    }

    // Constraint: set totSlack equal to the total slack
    lhs = 0;
    for (int s = 0; s < nShifts; ++s)
    {
      lhs += slacks[s];
    }
    model.addConstr(lhs == totSlack, "totSlack");

    // Constraint: compute the total number of shifts for each worker
    for (int w = 0; w < nWorkers; ++w) {
      lhs = 0;
      for (int s = 0; s < nShifts; ++s) {
        lhs += x[w][s];
      }
      ostringstream vname;
      vname << "totShifts" << Workers[w];
      model.addConstr(lhs == totShifts[w], vname.str());
    }

    // Objective: minimize the total slack
    GRBLinExpr obj = 0;
    obj += totSlack;
    model.setObjective(obj);

    // Optimize
    int status = solveAndPrint(model, totSlack, nWorkers, Workers, totShifts);
    if (status != GRB_OPTIMAL)
    {
      return 1;
    }

    // Constrain the slack by setting its upper and lower bounds
    totSlack.set(GRB_DoubleAttr_UB, totSlack.get(GRB_DoubleAttr_X));
    totSlack.set(GRB_DoubleAttr_LB, totSlack.get(GRB_DoubleAttr_X));

    // Variable to count the average number of shifts worked
    GRBVar avgShifts =
      model.addVar(0, GRB_INFINITY, 0, GRB_CONTINUOUS, "avgShifts");

    // Variables to count the difference from average for each worker;
    // note that these variables can take negative values.
    diffShifts = model.addVars(nWorkers);
    model.update();
    for (int w = 0; w < nWorkers; ++w) {
      ostringstream vname;
      vname << Workers[w] << "Diff";
      diffShifts[w].set(GRB_StringAttr_VarName, vname.str());
      diffShifts[w].set(GRB_DoubleAttr_LB, -GRB_INFINITY);
    }

    // Update model to integrate new variables
    model.update();

    // Constraint: compute the average number of shifts worked
    lhs = 0;
    for (int w = 0; w < nWorkers; ++w) {
      lhs += totShifts[w];
    }
    model.addConstr(lhs == nWorkers * avgShifts, "avgShifts");

    // Constraint: compute the difference from the average number of shifts
    for (int w = 0; w < nWorkers; ++w) {
      lhs = 0;
      lhs += totShifts[w];
      lhs -= avgShifts;
      ostringstream vname;
      vname << Workers[w] << "Diff";
      model.addConstr(lhs == diffShifts[w], vname.str());
    }

    // Objective: minimize the sum of the square of the difference from the
    // average number of shifts worked
    GRBQuadExpr qobj;
    for (int w = 0; w < nWorkers; ++w) {
      qobj += diffShifts[w] * diffShifts[w];
    }
    model.setObjective(qobj);

    // Optimize
    status = solveAndPrint(model, totSlack, nWorkers, Workers, totShifts);
    if (status != GRB_OPTIMAL)
    {
      return 1;
    }

  }
  catch (GRBException e)
  {
    cout << "Error code = " << e.getErrorCode() << endl;
    cout << e.getMessage() << endl;
  }
  catch (...)
  {
    cout << "Exception during optimization" << endl;
  }

  delete[] c;
  delete[] v;
  for (int i = 0; i < xCt; ++i) {
    delete[] x[i];
  }
  delete[] x;
  delete[] slacks;
  delete[] totShifts;
  delete[] diffShifts;
  delete env;
  return 0;
}
Beispiel #4
0
int
main(int argc,
     char *argv[])
{
  GRBEnv* env = 0;
  GRBVar* open = 0;
  GRBVar** transport = 0;
  int transportCt = 0;
  try
  {

    // Number of plants and warehouses
    const int nPlants = 5;
    const int nWarehouses = 4;

    // Warehouse demand in thousands of units
    double Demand[] = { 15, 18, 14, 20 };

    // Plant capacity in thousands of units
    double Capacity[] = { 20, 22, 17, 19, 18 };

    // Fixed costs for each plant
    double FixedCosts[] = { 12000, 15000, 17000, 13000, 16000 };

    // Transportation costs per thousand units
    double TransCosts[][nPlants] = {
                                     { 4000, 2000, 3000, 2500, 4500 },
                                     { 2500, 2600, 3400, 3000, 4000 },
                                     { 1200, 1800, 2600, 4100, 3000 },
                                     { 2200, 2600, 3100, 3700, 3200 }
                                   };

    // Model
    env = new GRBEnv();
    GRBModel model = GRBModel(*env);
    model.set(GRB_StringAttr_ModelName, "facility");

    // Plant open decision variables: open[p] == 1 if plant p is open.
    open = model.addVars(nPlants, GRB_BINARY);
    model.update();
    int p;
    for (p = 0; p < nPlants; ++p)
    {
      ostringstream vname;
      vname << "Open" << p;
      open[p].set(GRB_DoubleAttr_Obj, FixedCosts[p]);
      open[p].set(GRB_StringAttr_VarName, vname.str());
    }

    // Transportation decision variables: how much to transport from a plant p to a warehouse w
    transport = new GRBVar* [nWarehouses];
    int w;
    for (w = 0; w < nWarehouses; ++w)
    {
      transport[w] = model.addVars(nPlants);
      transportCt++;
      model.update();
      for (p = 0; p < nPlants; ++p)
      {
        ostringstream vname;
        vname << "Trans" << p << "." << w;
        transport[w][p].set(GRB_DoubleAttr_Obj, TransCosts[w][p]);
        transport[w][p].set(GRB_StringAttr_VarName, vname.str());
      }
    }

    // The objective is to minimize the total fixed and variable costs
    model.set(GRB_IntAttr_ModelSense, 1);

    // Update model to integrate new variables
    model.update();

    // Production constraints
    // Note that the right-hand limit sets the production to zero if
    // the plant is closed
    for (p = 0; p < nPlants; ++p)
    {
      GRBLinExpr ptot = 0;
      for (w = 0; w < nWarehouses; ++w)
      {
        ptot += transport[w][p];
      }
      ostringstream cname;
      cname << "Capacity" << p;
      model.addConstr(ptot <= Capacity[p] * open[p], cname.str());
    }

    // Demand constraints
    for (w = 0; w < nWarehouses; ++w)
    {
      GRBLinExpr dtot = 0;
      for (p = 0; p < nPlants; ++p)
      {
        dtot += transport[w][p];
      }
      ostringstream cname;
      cname << "Demand" << w;
      model.addConstr(dtot == Demand[w], cname.str());
    }

    // Guess at the starting point: close the plant with the highest
    // fixed costs; open all others

    // First, open all plants
    for (p = 0; p < nPlants; ++p)
    {
      open[p].set(GRB_DoubleAttr_Start, 1.0);
    }

    // Now close the plant with the highest fixed cost
    cout << "Initial guess:" << endl;
    double maxFixed = -GRB_INFINITY;
    for (p = 0; p < nPlants; ++p)
    {
      if (FixedCosts[p] > maxFixed)
      {
        maxFixed = FixedCosts[p];
      }
    }
    for (p = 0; p < nPlants; ++p)
    {
      if (FixedCosts[p] == maxFixed)
      {
        open[p].set(GRB_DoubleAttr_Start, 0.0);
        cout << "Closing plant " << p << endl << endl;
        break;
      }
    }

    // Use barrier to solve root relaxation
    model.getEnv().set(GRB_IntParam_Method, GRB_METHOD_BARRIER);

    // Solve
    model.optimize();

    // Print solution
    cout << "\nTOTAL COSTS: " << model.get(GRB_DoubleAttr_ObjVal) << endl;
    cout << "SOLUTION:" << endl;
    for (p = 0; p < nPlants; ++p)
    {
      if (open[p].get(GRB_DoubleAttr_X) == 1.0)
      {
        cout << "Plant " << p << " open:" << endl;
        for (w = 0; w < nWarehouses; ++w)
        {
          if (transport[w][p].get(GRB_DoubleAttr_X) > 0.0001)
          {
            cout << "  Transport " << transport[w][p].get(GRB_DoubleAttr_X) << " units to warehouse " << w << endl;
          }
        }
      }
      else
      {
        cout << "Plant " << p << " closed!" << endl;
      }
    }

  }
  catch (GRBException e)
  {
    cout << "Error code = " << e.getErrorCode() << endl;
    cout << e.getMessage() << endl;
  }
  catch (...)
  {
    cout << "Exception during optimization" << endl;
  }

  delete[] open;
  for (int i = 0; i < transportCt; ++i) {
    delete[] transport[i];
  }
  delete[] transport;
  delete env;
  return 0;
}
int main(int argc, char *argv[]) {

	// do we want to force integer solution?
	// if false, we solve a linear program without the integrity constraint
	bool integer_solution = false;
	// if objective_min_N is true then we solve the problem which minimizes total
	// number of vehicles in the simulation.
	// Otherwise, we minimize number of rebalancing trips
	bool objective_min_N = true;

	GRBEnv* env = 0; //< gurobi env
	GRBVar** rij = 0; // number of empty vehicles traveling between stations
	GRBVar** vi = 0; // number of vehicles available at station i

	// stations coordinates
	std::vector<std::vector<double> > stations;
	// distances or cost of traveling between the stations
	// internal vector stores "to where" and external vector stores "from where"
	std::vector<std::vector<double> > cost;
	// origin counts, size of n_rebalancing_periods x n_stations
	std::vector<std::vector<double> > origin_counts;
	// destination counts, size of n_rebalancing_periods x n_stations
	std::vector<std::vector<double> > dest_counts;
	// counts of vehicles in transit to each station, size of n_rebalancing_periods x n_stations
	std::vector<std::vector<double> > in_transit_counts;
	// cost of one idle vehicle in the system, when objective minimizes # vehicles, then set cost to 1,
	// when objective minimizes number of rebalancing vehicles then set cost to a huge number
	// (to make sure that this is always more expensive that rebalancing as it adds more vehicles to the system)
	double cost_of_veh = 1.0;
	double rebalancing_cost = 1.0;
	// what constraints do you want to take into account

	// input and output files declaration
	// simple_model
	//	bool simple_model = true;
	//	const string stationsFile = "/home/kasia/Dropbox/matlab/2015-09_FleetSizeEstimation/sampleFiles/stationsXY.txt";
	//	const string costMatrixFile = "/home/kasia/Dropbox/matlab/2015-09_FleetSizeEstimation/sampleFiles/costM3x3TT.txt";
	//	const string originCountsFile = "/home/kasia/Dropbox/matlab/2015-09_FleetSizeEstimation/sampleFiles/origCounts3x3TT.txt";
	//	const string destinationCountsFile = "/home/kasia/Dropbox/matlab/2015-09_FleetSizeEstimation/sampleFiles/destCounts3x3TT.txt";
	//	const string inTransitCountsFile = "/home/kasia/Dropbox/matlab/2015-09_FleetSizeEstimation/sampleFiles/inTransit3x3TT.txt";
	//	const string modelOutput = "rebalancing_formulation_simple.lp";
	//	const string solutionOutput = "rebalancing_solution_simple.sol";

	//	// simmobility files
	//		// ubuntu
	bool simple_model = false;
	const string stationsFile = "/home/kasia/Dropbox/matlab/2016-03-Demand_generation/facility_location/stations_ecbd34.txt";
	const string costMatrixFile = "/home/kasia/Dropbox/matlab/2015-09_FleetSizeEstimation/RebTimeInSecs34Stations.txt";
	const string originCountsFile = "/home/kasia/Dropbox/matlab/2015-09_FleetSizeEstimation/origCounts_rebEvery900_stations34.txt";
	const string destinationCountsFile = "/home/kasia/Dropbox/matlab/2015-09_FleetSizeEstimation/destCounts_rebEvery900_stations34.txt";
	const string inTransitCountsFile = "/home/kasia/Dropbox/matlab/2015-09_FleetSizeEstimation/inTransitReb900Stations34";
	const string modelOutput = "formulation_rebalancing.lp";
	const string solutionOutput = "rebalancing_solution.sol";

	// mac
	//		stationsFile = "/Users/katarzyna/Dropbox/matlab/2016-03-Demand_generation/facility_location/stations_ecbd34.txt";
	//		costMatrixFile = "/Users/katarzyna/Dropbox/matlab/2015-09_FleetSizeEstimation/RebTime34Stations.txt";
	//		originCountsFile = "/Users/katarzyna/Dropbox/matlab/2015-09_FleetSizeEstimation/origCounts_rebEvery900_stations34.txt";
	//		destinationCountsFile = "/Users/katarzyna/Dropbox/matlab/2015-09_FleetSizeEstimation/destCounts_rebEvery900_stations34.txt";


	//readFiles(stationsFile, stations);
	readFiles(costMatrixFile, cost);
	readFiles(originCountsFile, origin_counts);
	readFiles(destinationCountsFile, dest_counts);
	readFiles(inTransitCountsFile, in_transit_counts);

	//round cost of traveling between stations to be a multiple of the rebalancing period
	int reb_period = 1;
	if(!simple_model) {
		reb_period = 900; // in minutes, output from costOfRebalancing.m is in secs
	}

	int rounded_cost[cost.size()][cost.size()];
	for (unsigned int i = 0; i < cost.size(); i++){
		for (unsigned int j = 0; j < cost[0].size(); j++){
			if (i != j) {
				// cost in seconds from the beginning of the simulation
				rounded_cost[i][j] = roundUp((int)cost[i][j], reb_period);
				//std::cout << "roundUp((int)cost[" << i <<"][" << j << "] = " << rounded_cost[i][j] << std::endl;
			} else {
				rounded_cost[i][j] = 99999999; // 0
			}
		}
	}

	try {
		// number of stations in the network
		const int nStations = cost.size();
		const int nStSquare = pow (nStations, 2);
		//number of rebalancing periods = number of rows in the origin and destination counts, size of the first vector
		const int nRebPeriods = origin_counts.size();

		/***********************************************************************************
		 * Station matrix
		 ***********************************************************************************/
		// station matrix to access the elements of cost/rebalancing vectors
		// matrix form stores the indices of the cost vector i.e., for 3 stations [[0,1,2],[3,4,5],[6,7,8]]
		int stationMatrix [nStations][nStations];
		int indxCounter = 0;
		for(int i = 0; i < nStations; ++i) {
			for (int k = 0; k < nStations; ++k) {
				stationMatrix[i][k] = indxCounter;
				//std::cout << "stationMatrix["<< i<< "][" << k << "] = " << indxCounter << endl;
				indxCounter++;
			}
		}

		/***********************************************************************************
		 * Model
		 ***********************************************************************************/
		env = new GRBEnv();
		GRBModel model = GRBModel(*env);
		model.set(GRB_StringAttr_ModelName, "rebalancing");

		/***********************************************************************************
		 * Decision variables
		 ***********************************************************************************/
		int station;
		int time_;
		div_t divresult;
		// Number of vehicles available (idle) at each period of time and each station
		vi = new GRBVar* [nRebPeriods];
		// Number of empty vehicles traveling between stations
		rij = new GRBVar* [nRebPeriods];
		for ( time_ = 0; time_ < nRebPeriods; ++time_) {
			if (integer_solution) {
				vi[time_] = model.addVars(nStations, GRB_INTEGER);
				rij[time_] = model.addVars(nStSquare, GRB_INTEGER);
			} else {
				vi[time_] = model.addVars(nStations);
				rij[time_] = model.addVars(nStSquare);
			}
			model.update();
		}

		// Objective: minimize number of rebalancing trips
		if (!objective_min_N) {
			for ( time_ = 0; time_ < nRebPeriods; ++time_) {

				for (station = 0; station < nStations; ++station) {
					ostringstream cname;
					cname << "v_ti," << time_ << "," << station << ",0";

					// not minimized in the objective
					vi[time_][station].set(GRB_DoubleAttr_Obj, 0.0);
					vi[time_][station].set(GRB_StringAttr_VarName, cname.str());

				}
			}
			model.update();

			for ( time_ = 0; time_ < nRebPeriods; ++time_) {

				for(int depSt = 0; depSt < nStations; ++depSt){
					// std::cout << "departure station: " << depSt << std::endl;
					for (int arrSt = 0; arrSt < nStations; ++arrSt) {

						int idx = stationMatrix[depSt][arrSt];
						ostringstream vname;
						vname << "r_tij," << time_ << "," << depSt << ","<< arrSt;
						//std::cout << "nEmptyVhsTime." << time_ << "." << depSt << "."<< arrSt << "."<< idx << std::endl;

						if (depSt == arrSt) {
							// origin == destination
							// this variable should not exist because we do not send vehicles within the same station
							rij[time_][idx].set(GRB_DoubleAttr_Obj, 0.0);
							rij[time_][idx].set(GRB_StringAttr_VarName, vname.str());
							continue;
						}
						// std::cout << "nEmptyVhsTime." << time_ << ".indx." << station << ".from."<< divresult.quot << ".to." << divresult.rem << std:: endl;

						rij[time_][idx].set(GRB_DoubleAttr_Obj, rebalancing_cost * rounded_cost[depSt][arrSt]); // rebalancing_cost
						rij[time_][idx].set(GRB_StringAttr_VarName, vname.str());
					}
				}
			}
		} else { // Objective: minimize the total number of vehicles at time_ == 0
			// integer constraint relaxed
			ostringstream cname;
			ostringstream vname;
			for ( time_ = 0; time_ < nRebPeriods; ++time_) {

				for(int depSt = 0; depSt < nStations; ++depSt){
					cname.str("");
					cname.clear();
					cname << "v_ti," << time_ <<"," << depSt << ",0";
					if (time_ != 0) {
						cost_of_veh = 0.0;
					} else {
						cost_of_veh = 1.0;
					}
					vi[time_][depSt].set(GRB_DoubleAttr_Obj, cost_of_veh);
					vi[time_][depSt].set(GRB_StringAttr_VarName, cname.str());

					model.update();

					for (int arrSt = 0; arrSt < nStations; ++arrSt) {
						vname.str("");
						vname.clear();
						vname << "r_tij," << time_ << "," << depSt << ","<< arrSt;
						// std::cout << "Adding variable: r_tij," << time_ << "," << depSt << ","<< arrSt << " =  \n" << std::flush;
						int idx = stationMatrix[depSt][arrSt];

						if (depSt == arrSt) {
							rij[time_][idx].set(GRB_DoubleAttr_Obj, 0.0);
							rij[time_][idx].set(GRB_StringAttr_VarName, vname.str());
							// std::cout << "vname = " << vname.str() << "\n" << std::flush;
							// std::cout << "vname after clear= " << vname.str() << "\n" << std::flush;
							// std::cout << "Added variable: r_tij," << time_ << "," << depSt << ","<< arrSt << " = 0.0\n" << std::flush;
							continue;
						}

						if (time_ != 0) {
							rebalancing_cost = 0.0;
						} else {
							rebalancing_cost = 1.0;
						}

						int travel_time = (int) (rounded_cost[arrSt][depSt]/reb_period);
						// divresult.rem is start time of the arriving trips
						divresult = div (nRebPeriods + time_ - travel_time, nRebPeriods);

						// to prevent overwriting if there is sth already assigned to this variable
						if (rij[divresult.rem][idx].get(GRB_DoubleAttr_Obj) > 0) {

							if (travel_time > 1) {
								for (int k = 1; k < travel_time; ++k) {
									divresult = div (nRebPeriods + time_ - travel_time + k, nRebPeriods);
									// to prevent overwriting if there is sth already assigned to this variable
									if (rij[divresult.rem][idx].get(GRB_DoubleAttr_Obj) > 0) {
										continue;
									}
									rij[divresult.rem][idx].set(GRB_DoubleAttr_Obj, rebalancing_cost);
									vname.str("");
									vname.clear();
									vname << "r_tij," << divresult.rem << "," << depSt << ","<< arrSt;
									rij[divresult.rem][idx].set(GRB_StringAttr_VarName, vname.str());
									//std::cout << "Added variable: r_tij," << divresult.rem << "," << depSt << ","<< arrSt << " = " << rebalancing_cost << "\n" << std::flush;
								}
							}
							continue;
						}

						rij[divresult.rem][idx].set(GRB_DoubleAttr_Obj, rebalancing_cost);
						vname.str("");
						vname.clear();
						vname << "r_tij," << divresult.rem << "," << depSt << ","<< arrSt;
						rij[divresult.rem][idx].set(GRB_StringAttr_VarName, vname.str());
						//std::cout << "Added variable: r_tij," << divresult.rem << "," << depSt << ","<< arrSt << " = " << rebalancing_cost << "\n" << std::flush;

						if (travel_time > 1) {
							for (int k = 1; k < travel_time; ++k) {
								divresult = div (nRebPeriods + time_ - travel_time + k, nRebPeriods);
								// to prevent overwriting if there is sth already assigned to this variable
								if (rij[divresult.rem][idx].get(GRB_DoubleAttr_Obj) > 0) {
									continue;
								}
								rij[divresult.rem][idx].set(GRB_DoubleAttr_Obj, rebalancing_cost);
								vname.str("");
								vname.clear();
								vname << "r_tij," << divresult.rem << "," << depSt << ","<< arrSt;
								rij[divresult.rem][idx].set(GRB_StringAttr_VarName, vname.str());
								//std::cout << "Added variable: r_tij," << divresult.rem << "," << depSt << ","<< arrSt << " = " << rebalancing_cost << "\n" << std::flush;
							}
						}
					}
				}
			}
		}
		model.update();

		/***********************************************************************************
		 * Objective function
		 ***********************************************************************************/
		// The objective is to minimize the number of vehicles traveling in the network (and cost associated with it)
		// Optimization sense:  The default +1.0 value indicates that the objective is to minimize the
		// objective. Setting this attribute to -1 changes the sense to maximization
		model.set(GRB_IntAttr_ModelSense, 1);
		model.update();

		/***********************************************************************************
		 * Constraint 1: The number of vehicles must be sufficient to serve the demand
		 ***********************************************************************************/
		// This constraint is set to ensure that the number of vehicles available at each station i
		// is sufficient to serve the demand within this station.
		// If there is not enough vehicles, then we do rebalancing to make sure we can serve the trips
		for ( time_ = 0; time_ < nRebPeriods; ++time_) {
			// Current demand
			int booking_requests[nStations];
			for (int i = 0; i < nStations; ++i) {
				// booking_requests = departing_vehicles - arriving_vehicles (how many more vehicles do we need)
				booking_requests[i] = origin_counts[time_][i] - dest_counts[time_][i];
				// std::cout << origin_counts[time_][i] << " - " << dest_counts[time_][i] << " = " << dem_curr[i] << std::endl;
			}

			GRBLinExpr reb_dep = 0;
			GRBLinExpr reb_arr = 0;

			for(int depSt = 0; depSt < nStations; ++depSt){
				// std::cout << "departure station: " << depSt << std::endl;
				for (int arrSt = 0; arrSt < nStations; ++arrSt) {

					if (depSt != arrSt) {
						int idx = stationMatrix[depSt][arrSt];
						int idx2 = stationMatrix[arrSt][depSt];
						reb_dep += rij[time_][idx];
						// std::cout << "rounded_cost = " << (int)rounded_cost[depSt][arrSt]/reb_period -1 << std::endl;
						// cost is expressed in the number of reb periods, i.e., 1,2,3,...nRebPeriods
						int travel_cost = (int) (rounded_cost[depSt][arrSt]/reb_period); // maybe ceil would be better than just int
						// ceil version of the above line
						// int travel_cost = (int) ceil((rounded_cost[depSt][arrSt]/reb_period));
						if (travel_cost > time_) {
							int dep_time = nRebPeriods + time_ - travel_cost;
							reb_arr += rij[dep_time][idx2];
						} else {
							int dep_time = time_ - travel_cost;
							reb_arr += rij[dep_time][idx2];
						}
					}
				}
				ostringstream cname;
				cname << "demand_ti" << time_ << "." << depSt;
				model.addConstr(vi[time_][depSt] + reb_arr - reb_dep >= booking_requests[depSt], cname.str());

				//std::cout << "Constraint 1 demand: " << time_  << "." << depSt << std::endl;
				reb_arr.clear();
				reb_dep.clear();
			}
		}
		model.update();
		std::cout << "Constraint set 1 added." << std::endl;

		/***********************************************************************************
		 * Constraint 2: Constant number of vehicles over time
		 ***********************************************************************************/
		// This constraint is set to ensure that the total number of vehicles in the system does not change
		// over time
		// the total number of vehicles in the system is equal to the sum of the vehicles owned by each station
		// vehicles owned by station i: available_veh + cust_arriving + cust_in_transit_to_station + empty_arr + empty_in_transit

		int cust_balance_at[nStations];
		int cust_vhs_at_t[time_];
		for ( time_ = 0; time_ < nRebPeriods; ++time_) {
			cust_vhs_at_t[time_] = 0;
			for (int i = 0; i < nStations; ++i) {
				// vhs_owned is the number of vehicles owned by station i
				// this number does not account for rebalancing vehicles
				// vhs_owned = arriving_costomers + in_transit_to_station
				cust_balance_at[i] = dest_counts[time_][i] + in_transit_counts[time_][i];
				// std::cout << "vhs_owned[" << i << "] = " << vhs_owned[i] << std::endl;
				cust_vhs_at_t[time_] += cust_balance_at[i];
			}
			if (time_ == 0) { // one print function to validate the above loop
				std::cout << "cust_vhs_at_t[" << time_ << "] = " << cust_vhs_at_t[time_] << std::endl;
			}
		}

		GRBLinExpr idle_veh = 0; // Gurobi Linear Expression, total number of idle vehicles now
		GRBLinExpr reb_arr = 0; // Gurobi Linear Expression, total number of rebalancing vehicles arriving and in transit to station i

		GRBLinExpr idle_veh_prev = 0; // Gurobi Linear Expression, total number of idle vehicles at previous interval
		GRBLinExpr reb_arr_prev = 0; // Gurobi Linear Expression, total number of rebalancing vehicles arriving and in transit to station i at previous time

		for ( time_ = 0; time_ < nRebPeriods; ++time_) {
			std::cout << "time_ = " << time_ << std::endl;

			// adding variables at current time t
			for(int i = 0; i < nStations; ++i) {
				// idle vehicles at station i at time t
				idle_veh += vi[time_][i];

				for(int j = 0; j < nStations; ++j) {
					if (i != j) {

						// travel_time is expressed in the number of reb periods, i.e., 1,2,3,...nRebPeriods
						// travel_time for trips arriving to i from j
						int travel_time = (int) (rounded_cost[j][i]/reb_period);
						// index of vehicles arriving at i from j (departed from j to i travel_time ago)
						int idx_arr = stationMatrix[j][i];
						// divresult.rem is start time of the arriving trips
						divresult = div (nRebPeriods + time_ - travel_time, nRebPeriods);
						// std::cout << "Current time = " << time_ << ", travel_time = " << travel_time << ", divresult.rem = " << divresult.rem << ", idx_arr = "<< idx_arr << std::endl;
						reb_arr += rij[divresult.rem][idx_arr];
						// empty trips in transit (not arriving yet)
						// if tt > 1 -> all trips started after divresult.rem and before time_
						if (travel_time > 1) {
							for (int k = 1; k < travel_time; ++k) {
								divresult = div (nRebPeriods + time_ - travel_time + k, nRebPeriods);
								// std::cout << "if travel_time > 1 => " << time_ << ", travel_time = " << travel_time << ", divresult.rem = " << divresult.rem << ", idx_arr = "<< idx_arr << std::endl;
								reb_arr += rij[divresult.rem][idx_arr];
							}
						}
					}
				}
			}

			// adding variables at time (t-1)
			for(int i = 0; i < nStations; ++i) {
				// idle vehicles at station i at time (t - 1)
				divresult = div (nRebPeriods + time_ - 1, nRebPeriods);
				idle_veh_prev += vi[divresult.rem][i];

				for(int j = 0; j < nStations; ++j) {
					if (i != j) {

						// travel_time is expressed in the number of reb periods, i.e., 1,2,3,...nRebPeriods
						// travel_time for trips arriving to i from j
						int travel_time = (int) (rounded_cost[j][i]/reb_period);
						// index of vehicles arriving at i from j (departed from j to i travel_time ago)
						int idx_arr = stationMatrix[j][i];
						// divresult.rem is start time of the arriving trips
						divresult = div (nRebPeriods + time_ - 1 - travel_time, nRebPeriods);
						// std::cout << "Previous time = " << nRebPeriods + time_ - 1 << ", travel_time = " << travel_time << ", divresult.rem = " << divresult.rem << ", idx_arr = "<< idx_arr << std::endl;
						reb_arr_prev += rij[divresult.rem][idx_arr];
						// empty trips in transit (not arriving yet)
						// if tt > 1 -> all trips started after divresult.rem and before time_
						if (travel_time > 1) {
							for (int k = 1; k < travel_time; ++k) {
								divresult = div (nRebPeriods + time_ - 1 - travel_time + k, nRebPeriods);
								reb_arr_prev += rij[divresult.rem][idx_arr];
							}
						}
					}
				}
			}

			// add constraints
			ostringstream cname;
			cname << "supply_t" << time_ ;

			// total number of vehicles at time t == total number of vehicles at time (t-1)
			divresult = div (nRebPeriods + time_ - 1, nRebPeriods);
			model.addConstr(idle_veh + reb_arr + cust_vhs_at_t[time_] == idle_veh_prev + reb_arr_prev + cust_vhs_at_t[divresult.rem], cname.str());
			model.update();

			idle_veh.clear();
			idle_veh_prev.clear();
			reb_arr.clear();
			reb_arr_prev.clear();

		} // end constraints loop: for ( time_ = 0; time_ < nRebPeriods; ++time_)
		std::cout << "Constraint set 2 added." << std::endl;

		/***********************************************************************************
		 * Constraint 3: Flow conservation at station i
		 ***********************************************************************************/
		// This constraint is set to ensure that the number of vehicles available at station i at time t
		// is equal to the number of vehicles available at this station in previous time interval
		// plus whatever has arrived minus whatever has departed
		for ( time_ = 0; time_ < nRebPeriods; ++time_) {
			// Current demand
			int dem_curr[nStations];
			for (int i = 0; i < nStations; ++i) {
				// current demand = arriving_vehicles - departing_vehicles
				dem_curr[i] = dest_counts[time_][i] - origin_counts[time_][i];
				// std::cout << origin_counts[time_][i] << " - " << dest_counts[time_][i] << " = " << dem_curr[i] << std::endl;
			}

			GRBLinExpr reb_dep = 0;
			GRBLinExpr reb_arr = 0;

			for(int depSt = 0; depSt < nStations; ++depSt){
				// std::cout << "departure station: " << depSt << std::endl;
				for (int arrSt = 0; arrSt < nStations; ++arrSt) {

					if (depSt != arrSt) {
						int idx = stationMatrix[depSt][arrSt];
						int idx2 = stationMatrix[arrSt][depSt];
						reb_dep += rij[time_][idx];
						// std::cout << "rounded_cost = " << (int)rounded_cost[depSt][arrSt]/reb_period -1 << std::endl;
						int travel_cost = (int) (rounded_cost[depSt][arrSt]/reb_period);
						if (travel_cost > time_) {
							int dep_time = nRebPeriods + time_ - travel_cost;
							reb_arr += rij[dep_time][idx2];
						} else {
							int dep_time = time_ - travel_cost;
							reb_arr += rij[dep_time][idx2];
						}
					}
				}
				ostringstream cname;
				cname << "flow_ti" << time_ << "." << depSt;
				if (time_ != nRebPeriods - 1) {
					model.addConstr(vi[time_ + 1][depSt] ==
							vi[time_][depSt] + reb_arr - reb_dep + dem_curr[depSt], cname.str());
				} else {
					// if we are in the last interval then we compare against the first interval of the next day
					// here: vi(t=0) == vi(t=Tp)
					model.addConstr(vi[0][depSt] ==
							vi[time_][depSt] + reb_arr - reb_dep + dem_curr[depSt], cname.str());
				}
				//std::cout << "Constraint 1 vi @: " << time_  << "." << depSt << std::endl;
				reb_arr.clear();
				reb_dep.clear();
			}
		}
		model.update();
		std::cout << "Constraint set 3 added." << std::endl;
		/***********************************************************************************
		 * Solve the problem and print solution to the console and to the file
		 ***********************************************************************************/
		model.optimize();
		model.write(modelOutput);

		int total_demand = 0;
		int dem_curr[nStations];
		for (int i = 0; i < nStations; ++i) {
			dem_curr[i] = dest_counts[0][i] + in_transit_counts[0][i];
			total_demand += dem_curr[i];
		}

		double numOfVeh = model.get(GRB_DoubleAttr_ObjVal) + total_demand; //plus rebalancing counts

		cout << "\nTOTAL NUMBER OF VEHICLES: " << numOfVeh << std::endl;
		cout << "\nTOTAL NUMBER OF AVAILABLE VEH AT TIME 0: " << model.get(GRB_DoubleAttr_ObjVal) << std::endl;
		//		cout << "SOLUTION:" << endl;
		//
		//		for (time_ = 0; time_ < nRebPeriods; ++time_){
		//
		//			for(int depSt = 0; depSt < nStations; ++depSt){
		//				for (int arrSt = 0; arrSt < nStations; ++arrSt) {
		//					if(depSt != arrSt) {
		//						int idx = stationMatrix[depSt][arrSt];
		//						cout << "At time " << time_ << ", rebalancing from station " << depSt <<
		//								" to station " << arrSt << " send "  <<
		//								empty_veh[time_][idx].get(GRB_DoubleAttr_X) << " vehicles." << std::endl;
		//					}
		//				}
		//			}
		//		}
		//
		//		for (time_ = 0; time_ < nRebPeriods; ++time_){
		//			for(int arrSt = 0; arrSt < nStations; ++arrSt){
		//				cout << "At time " << time_ << " at station " << arrSt <<
		//						" number of available vehicles: " << vhs_st_i[time_][arrSt].get(GRB_DoubleAttr_X) << std::endl;
		//			}
		//			cout << "At time " << time_ << " number of vehicles in transit: "
		//					<< in_transit[time_].get(GRB_DoubleAttr_X) << std::endl;
		//		}

		model.write(solutionOutput);

	} catch(GRBException e) {
		cout << "Error code = " << e.getErrorCode() << std::endl;
		cout << e.getMessage() << std::endl;
	} catch(...) {
		cout << "Exception during optimization" << std::endl;
	}
	return 0;
}
Beispiel #6
0
int
main(int argc,
     char *argv[])
{
  GRBEnv* env = 0;
  GRBVar* nutrition = 0;
  GRBVar* buy = 0;
  try
  {

    // Nutrition guidelines, based on
    // USDA Dietary Guidelines for Americans, 2005
    // http://www.health.gov/DietaryGuidelines/dga2005/
    const int nCategories = 4;
    string Categories[]   = { "calories",    "protein",  "fat", "sodium" };
    double minNutrition[] = {       1800,           91,     0,        0 };
    double maxNutrition[] = {       2200, GRB_INFINITY,    65,     1779 };

    // Set of foods
    const int nFoods = 9;
    string Foods[] = { "hamburger", "chicken", "hot dog", "fries", "macaroni", "pizza", "salad", "milk", "ice cream" };
    double cost[]  = { 2.49,             2.89,      1.50,    1.89,       2.09,    1.99,    2.49,   0.89,       1.59 };

    // Nutrition values for the foods
    double nutritionValues[][nCategories] = {
                      { 410, 24, 26,  730 },   // hamburger
                      { 420, 32, 10, 1190 },   // chicken
                      { 560, 20, 32, 1800 },   // hot dog
                      { 380,  4, 19,  270 },   // fries
                      { 320, 12, 10,  930 },   // macaroni
                      { 320, 15, 12,  820 },   // pizza
                      { 320, 31, 12, 1230 },   // salad
                      { 100,  8, 2.5, 125 },   // milk
                      { 330,  8, 10,  180 }    // ice cream
                    };

    // Model
    env = new GRBEnv();
    GRBModel model = GRBModel(*env);
    model.set(GRB_StringAttr_ModelName, "diet");

    // Create decision variables for the nutrition information,
    // which we limit via bounds
    nutrition = model.addVars(minNutrition, maxNutrition, 0, 0, Categories, nCategories);

    // Create decision variables for the foods to buy
    buy = model.addVars(0, 0, cost, 0, Foods, nFoods);

    // The objective is to minimize the costs
    model.set(GRB_IntAttr_ModelSense, 1);

    // Update model to integrate new variables
    model.update();

    // Nutrition constraints
    for (int i = 0; i < nCategories; ++i)
    {
      GRBLinExpr ntot = 0;
      for (int j = 0; j < nFoods; ++j)
      {
        ntot += nutritionValues[j][i] * buy[j];
      }
      model.addConstr(ntot == nutrition[i], Categories[i]);
    }

    // Solve
    model.optimize();
    printSolution(model, nCategories, nFoods, buy, nutrition);

    // Add constraint
    cout << "\nAdding constraint: at most 6 servings of dairy" << endl;
    model.addConstr(buy[7] + buy[8] <= 6.0, "limit_dairy");

    // Solve
    model.optimize();
    printSolution(model, nCategories, nFoods, buy, nutrition);

  }
  catch (GRBException e)
  {
    cout << "Error code = " << e.getErrorCode() << endl;
    cout << e.getMessage() << endl;
  }
  catch (...)
  {
    cout << "Exception during optimization" << endl;
  }

  delete[] nutrition;
  delete[] buy;
  delete env;
  return 0;
}