Search code examples
loopscplexread-data

Cplex: How to read different data input from dat.file in a for loop


I am stuck with a flow control problem and failed to get a way out from the given CPLEX examples. I want to solve the optimization problem for 16 times, and the only thing that differs is the input of demand. (Because we have trouble running the “SheetConnection” code in our server so I want to build the model that reads raw data from dat file).

I have 16 demands for 16 different periods. For the 1st run, I want the demand of the model to be the 1st number of the demand array. And for the nth run, the demand of the model to be the nth number of the demand array.

I have already modified the model from the CPLEX example “mulprod”, but I found that the example changes the capacity of flour increasingly (by adding 1 unit every time). So, it didn’t mention how to read the data in order. I guess the problem lies in if I want to set Demand as a range in the beginning, then my code to call the nth number is problematic.

/*mod.file*/
{string} Units_ = ...;
int NbUnits = ...;
range Units = 1..NbUnits;
int NbLoops = ...;

float Demand[1..16] = ...;
float MaxGen [Units] = ...; 
float MinGen [Units] = ...; 
float MarginalC [Units] = ...; 

dvar boolean Opr [u in Units];
dvar float+ Gen [u in Units] in 0..MaxGen [u];

execute {
  writeln("* This OPL model is not compliant with cloud execution");
}

minimize 
  sum(u in Units) (Gen[u] * MarginalC[u]);

subject to {
//Meet demand       
      ctPowerBalance: 
        sum(u in Units) Gen[u] == Demand;  
//Max/Min Unit Constraints           
    forall(u in Units)
      ctMaxGeneration:
        Gen[u] <= MaxGen[u]*Opr[u];
    forall(u in Units)
      ctMinGeneration:
        Gen[u] >= MinGen[u]*Opr[u];
}

tuple plan {
  float Operation;
  float Generation;
}

plan Plan[u in Units] = 
  <Opr[u], Gen[u]>;



main {
  thisOplModel.generate();

  var produce = thisOplModel;
  var Demandt = produce.Demand_[NbLoops];

  var best;
  var curr = Infinity;
  var ofile = new IloOplOutputFile("BAU_T2030.txt");
  while ( 1 ) {
    best = curr;
    writeln("Solve with Demand[", NbLoops, "] is ", Demandt);
    if ( cplex.solve() ) {
      curr = cplex.getObjValue();
      writeln();
      writeln("OBJECTIVE: ",curr);
      ofile.writeln("Objective with Demand[", NbLoops, "] is ", curr);
      ofile.writeln("plan = ",produce.Plan);      
} 
    else {
      writeln("No solution!");
      break;
    }
    if ( best==curr ) break;

NbLoops ++;
    for(var Demand in thisOplModel.Demand)          
      thisOplModel.ctPowerBalance[Demand].UB = Demandt;
  }

  ofile.close();

  0;
}

/*dat.file*/
Units_ = {G11, G12, G13, G14, G15};
NbUnits = 5;
NbLoops = 1;
Demand = [1133.16, 1826.47, 1304.79, 1330.03, 1556.02, 1952.19, 1124.82, 1622.05, 1567.69, 1499.43, 1315.01, 1135.05, 1029.67, 1949.19, 1972.64, 1812.24];
MaxGen = [519.2, 665.6, 46.5, 212, 464];
MarginalC = [55.21, 36.32, 41.62, 34.16, 36.71]; 

Solution

  • this is flow control with incremental in https://www.linkedin.com/pulse/making-decision-optimization-simple-alex-fleischer/

    .mod

    {string} Units_ = ...;
    int NbUnits = ...;
    range Units = 1..NbUnits;
    int NbLoops = ...;
    
    float Demand[1..16] = ...;
    float MaxGen [Units] = ...; 
    float MinGen [Units] = ...; 
    float MarginalC [Units] = ...; 
    
    dvar boolean Opr [u in Units];
    dvar float+ Gen [u in Units] in 0..MaxGen [u];
    
    dvar float currentDemand;
    
    execute {
      writeln("* This OPL model is not compliant with cloud execution");
    }
    
    minimize 
      sum(u in Units) (Gen[u] * MarginalC[u]);
    
    subject to {
    //Meet demand       
          ctPowerBalance: 
            sum(u in Units) Gen[u] == currentDemand;  
    //Max/Min Unit Constraints           
        forall(u in Units)
          ctMaxGeneration:
            Gen[u] <= MaxGen[u]*Opr[u];
        forall(u in Units)
          ctMinGeneration:
            Gen[u] >= MinGen[u]*Opr[u];
    }
    
    tuple plan {
      float Operation;
      float Generation;
    }
    
    plan Plan[u in Units] = 
      <Opr[u], Gen[u]>;
    
    
    
    main {
      thisOplModel.generate();
     var NbLoops=1;
      var produce = thisOplModel;
    
    
      var best;
      //var curr = Infinity;
      var ofile = new IloOplOutputFile("BAU_T2030.txt");
      while ( NbLoops<=16 ) {
        var Demandt = produce.Demand[NbLoops];
        //best = curr;
        writeln("Solve with Demand[", NbLoops, "] is ", Demandt);
        if ( cplex.solve() ) {
          curr = cplex.getObjValue();
          writeln();
          writeln("OBJECTIVE: ",curr);
          ofile.writeln("Objective with Demand[", NbLoops, "] is ", curr);
          ofile.writeln("plan = ",produce.Plan);      
    } 
        else {
          writeln("No solution!");
          //break;
        }
        //if ( best==curr ) break;
    
    NbLoops ++;
        //for(var Demand in thisOplModel.Demand)          
          thisOplModel.currentDemand.UB = Demandt;
          thisOplModel.currentDemand.LB = Demandt;
      }
    
      ofile.close();
    
      0;
    }
    

    .dat

    Units_ = {G11, G12, G13, G14, G15};
    NbUnits = 5;
    NbLoops = 16;
    Demand = [1133.16, 1826.47, 1304.79, 1330.03, 1556.02, 1952.19, 1124.82, 1622.05, 1567.69, 1499.43, 1315.01, 1135.05, 1029.67, 1949.19, 1972.64, 1812.24];
    MaxGen = [519.2, 665.6, 46.5, 212, 464];
    MinGen = [];
    MarginalC = [55.21, 36.32, 41.62, 34.16, 36.71]; 
    

    works better