Modifying an Optimization Problem: Example ilolpex3.cpp

This example demonstrates:

Here is the problem example ilolpex3 solves:

Minimize 
c*x 


 

subject to 
Hx = d  
Ax = b  
1 x


 

where 
H =  

( -1 0 1 0 1 0 0 0 )

d =  

( -3 )

 
 

( 1 -1 0 1 0 0 0 0 )

 

( 1 )

 
 

( 0 1 -1 0 0 1 -1 0 )

 

( 4 )

 
 

( 0 0 0 -1 0 -1 0 1 )

 

( 3 )

 
 

( 0 0 0 0 -1 0 1 -1 )

 

( -5 )

 
 

 

 
A =  

( 2 1 -2 -1 2 -1 -2 -3 )

b =  

( 4 )

 
 

( 1 -3 2 3 -1 2 1 1 )

 

( -2 )

 
 

 

 
c =  

(-9 1 4 2 -8 2 8 12 )

 

 
l =  

( 0 0 0 0 0 0 0 0 )

 

 
u =  

(50 50 50 50 50 50 50 50 )

 

The constraints Hx=d represent a pure network flow. The example solves this problem in two steps:

  1. The CPLEX Network Optimizer is used to solve

    Minimize 
    c*x 
    subject to 
    Hx = d 
    1 x u 

  2. The constraints Ax=b are added to the problem, and the dual simplex optimizer is used to solve the full problem, starting from the optimal basis of the network problem. The dual simplex method is highly effective in such a case because this basis remains dual feasible after the slacks (artificial variables) of the added constraints are initialized as basic.

Notice that the 0 values in the data are omitted in the example program. CPLEX makes extensive use of sparse matrix methods and, although CPLEX correctly handles any explicit zero coefficients given to it, most programs solving models of more than modest size benefit (in terms of both storage space and speed) if the natural sparsity of the model is exploited from the very start.

Before the model is solved, the network optimizer is selected by setting the RootAlg parameter to the value IloCplex::Network, as shown in example ilolpex2.cpp. The simplex display parameter IloCplex::SimDisplay is set so that the simplex algorithm issues logging information as it executes.

Setting CPLEX Parameters

IloCplex provides a variety of parameters that allow you to control the solution process. They can be categorized into boolean, integer, numerical and string parameters and are represented by the enumeration types IloCplex::BoolParam, IloCplex::IntParam, IloCplex::NumParam, and IloCplex::StringParam, respectively.

Modifying an Optimization Problem

After the simple model is solved and the resulting objective value is passed to the output channel cplex.out(), the remaining constraints are created and added to the model. At this time the model has already been extracted to cplex. As a consequence, whenever the model is modified by adding a constraint, this addition is immediately reflected in the cplex object via notification.

Starting from a Previous Basis

Before solving the modified problem, example ilolpex3.cpp sets the optimizer option to IloCplex::Dual, as this is the algorithm that can generally take best advantage of the optimal basis from the previous solve after the addition of constraints.

Complete Program

The complete program follows. You can also view it online in the file ilolpex3.cpp.

  // -------------------------------------------------------------- -*- C++ -*-
  // File: examples/src/ilolpex3.cpp
  // Version 8.1
  // --------------------------------------------------------------------------
  //  Copyright (C) 1999-2002 by ILOG.
  //  All Rights Reserved.
  //  Permission is expressly granted to use this example in the
  //  course of developing applications that use ILOG products.
  // --------------------------------------------------------------------------
  //
  // ilolpex3.cpp, example of adding constraints to solve a problem
  //
  // Modified example from Chvatal, "Linear Programming", Chapter 26.
  //   minimize  c*x
  //   subject to  Hx = d
  //               Ax = b
  //               l <= x <= u
  //   where
  //
  //   H = ( -1  0  1  0  1  0  0  0 )  d = ( -3 )
  //       (  1 -1  0  1  0  0  0  0 )      (  1 )
  //       (  0  1 -1  0  0  1 -1  0 )      (  4 )
  //       (  0  0  0 -1  0 -1  0  1 )      (  3 )
  //       (  0  0  0  0 -1  0  1 -1 )      ( -5 )
  //
  //   A = (  2  1 -2 -1  2 -1 -2 -3 )  b = (  4 )
  //       (  1 -3  2  3 -1  2  1  1 )      ( -2 )
  //
  //   c = ( -9  1  4  2 -8  2  8 12 )
  //   l = (  0  0  0  0  0  0  0  0 )
  //   u = ( 50 50 50 50 50 50 50 50 )
  //
  //
  //
  //  Treat the constraints with A as the complicating constraints, and
  //  the constraints with H as the "simple" problem.
  //
  //  The idea is to solve the simple problem first, and then add the
  //  constraints for the complicating constraints, and solve with dual.
  
  #include <ilcplex/ilocplex.h>
  ILOSTLBEGIN
  
  int main()
  {
     IloEnv   env;
     try {
        IloModel model(env, "chvatal");
  
        IloNumVarArray x(env, 8, 0, 50);
        model.add(IloMinimize(env,-9*x[0] + x[1] + 4*x[2] + 2*x[3]
                                  -8*x[4] + 2*x[5] + 8*x[6] + 12*x[7]));
        model.add(-x[0]        + x[2]        + x[4]                      == -3);
        model.add( x[0] - x[1]        + x[3]                             ==  1);
        model.add(        x[1] - x[2]               + x[5] - x[6]        ==  4);
        model.add(                    - x[3]        - x[5]        + x[7] ==  3);
        model.add(                           - x[4]        + x[6] - x[7] == -5);
  
        IloCplex cplex(model);
        cplex.setParam(IloCplex::SimDisplay, 2);
        cplex.setParam(IloCplex::RootAlg, IloCplex::Network);
        cplex.solve();
        cplex.out() << "After network optimization, objective is "
                    << cplex.getObjValue() << endl;
  
        model.add(2*x[0] + 1*x[1] - 2*x[2] - 1*x[3] +
                  2*x[4] - 1*x[5] - 2*x[6] - 3*x[7] ==  4);
        model.add(1*x[0] - 3*x[1] + 2*x[2] + 3*x[3] -
                  1*x[4] + 2*x[5] + 1*x[6] + 1*x[7] == -2);
  
        cplex.setParam(IloCplex::RootAlg, IloCplex::Dual);
        cplex.solve();
  
        IloNumArray vals(env);
        cplex.getValues(vals, x);
        cplex.out() << "Solution status " << cplex.getStatus() << endl;
        cplex.out() << "Objective value " << cplex.getObjValue() << endl;
        cplex.out() << "Solution is: " << vals << endl;
  
        cplex.exportModel("lpex3.sav");
     }
     catch (IloException& e) {
        cerr << "Concert exception caught: " << e << endl;
     }
     catch (...) {
        cerr << "Unknown exception caught" << endl;
     }
  
     env.end();
     return 0;
  } // END main
  


Previous Page: Modifying and Reoptimizing  Return to Top Next Page: Concert Technology for Java Users