> Continuous Optimization > Solving Network-Flow Problems > Example: Network to LP Transformation netex2.c

This example shows how to transform a network-flow problem into its corresponding LP formulation. That example also indicates why you might want to make such a change. The example reads a network-flow problem from a file (rather than populating the problem object by adding rows and columns as in netex1.c). It then attempts to solve the problem by calling the Callable Library routine CPXNETprimopt. If it determines that the problem is infeasible, it then transforms the problem into its LP formulation so that the infeasibility finder can analyze the problem and possibly indicate the cause of the infeasibility in an irreducibly inconsistent set (IIS). To perform this analysis, the application calls the Callable Library routine CPXiiswrite to write the IIS to the file netex2.iis.

The complete program, netex2.c, appears here and online in the standard distribution.

/*------------------------------------------------------------------------*/
/*  File: examples/src/netex2.c                                           */
/*  Version 9.0                                                           */
/*------------------------------------------------------------------------*/
/*  Copyright (C) 1997-2003 by ILOG.                                      */
/*  All Rights Reserved.                                                  */
/*  Permission is expressly granted to use this example in the            */
/*  course of developing applications that use ILOG products.             */
/*------------------------------------------------------------------------*/

/* netex2.c - Reading and optimizing a network problem.
              Transforming to LP to find IIS. */

/* Import the CPLEX function declarations and the C library 
   header file stdio.h with the following single include. */

#include <ilcplex/cplex.h>

/* Import the declarations for the string functions */

#include <string.h>



int
main (int argc, char **argv)
{
   /* Declare variables and arrays for retrieving problem data and
      solution information later on. */

   int       status = 0;
   CPXENVptr env = NULL;
   CPXNETptr net = NULL;
   CPXLPptr  lp  = NULL;

   /* Check command line */

   if ( argc != 2 ) {
      fprintf (stderr, "Usage: %s <network file>\n", argv[0]);
      fprintf (stderr, "Exiting ...\n");
      goto TERMINATE;
   }

   /* Initialize the CPLEX environment */

   env = CPXopenCPLEX (&status);

   /* If an error occurs, the status value indicates the reason for
      failure.  A call to CPXgeterrorstring will produce the text of
      the error message.  Note that CPXopenCPLEX produces no
      output, so the only way to see the cause of the error is to use
      CPXgeterrorstring.  For other CPLEX routines, the errors will
      be seen if the CPX_PARAM_SCRIND indicator is set to CPX_ON.  */

   if ( env == NULL ) {
      char  errmsg[1024];
      fprintf (stderr, "Could not open CPLEX environment.\n");
      CPXgeterrorstring (env, status, errmsg);
      fprintf (stderr, "%s", errmsg);
      goto TERMINATE;
   }

   /* Turn on output to the screen */

   status = CPXsetintparam (env, CPX_PARAM_SCRIND, CPX_ON);
   if ( status ) {
      fprintf (stderr, 
               "Failure to turn on screen indicator, error %d.\n", status);
      goto TERMINATE;
   }

   /* Create the problem. */

   net = CPXNETcreateprob (env, &status, "netex2");

   /* A returned pointer of NULL may mean that not enough memory
      was available or there was some other problem.  In the case of 
      failure, an error message will have been written to the error 
      channel from inside CPLEX.  In this example, the setting of
      the parameter CPX_PARAM_SCRIND causes the error message to
      appear on stdout.  */

   if ( net == NULL ) {
      fprintf (stderr, "Failed to create network object.\n");
      goto TERMINATE;
   }

   /* Read network problem data from file
      with filename given as command line argument. */

   status = CPXNETreadcopyprob (env, net, argv[1]);

   if ( status ) {
      fprintf (stderr, "Failed to build network problem.\n");
      goto TERMINATE;
   }

   /* Optimize the problem */

   status = CPXNETprimopt (env, net);
   if ( status ) {
      fprintf (stderr, "Failed to optimize network.\n");
      goto TERMINATE;
   }

   /* Check network solution status */

   if ( CPXNETgetstat (env, net) == CPX_STAT_INFEASIBLE ) {

      /* Create LP object used for invoking infeasibility finder */

      lp = CPXcreateprob (env, &status, "netex2");
      if ( lp == NULL ) {
         fprintf (stderr, "Failed to create LP object.\n");
         goto TERMINATE;
      }

      /* Copy LP representation of network problem to lp object, along
         with the current basis available in the network object. */

      status = CPXcopynettolp (env, lp, net);
      if ( status ) {
         fprintf (stderr, "Failed to copy network as LP.\n");
         goto TERMINATE;
      }

      /* Optimize the LP with primal to create an LP solution.  This
         optimization will start from the basis previously generated by
         CPXNETprimopt() as long as the advance indicator is switched
         on (its default).  */

      status = CPXsetintparam (env, CPX_PARAM_LPMETHOD, CPX_ALG_PRIMAL);
      if ( status ) {
         fprintf (stderr, 
                  "Failure to set LP method, error %d.\n", status);
         goto TERMINATE;
      }
  
      status = CPXlpopt (env, lp);
      if ( status ) {
         fprintf (stderr, "Failed to optimize LP.\n");
         goto TERMINATE;
      }

      /* Find IIS and write it to a file */

      status = CPXiiswrite (env, lp, "netex2.iis");
      if ( status ) {
         fprintf (stderr, "Failed to find IIS or write IIS file\n");
         goto TERMINATE;
      }

      printf ("IIS written to file netex2.iis\n");
   }
   else {
      printf ("Network problem not proved to be infeasible\n");
   }
   
TERMINATE:

   /* Free up the problem as allocated by CPXNETcreateprob, if necessary */

   if ( net != NULL ) {
      CPXNETfreeprob (env, &net);
      if ( status ) {
         fprintf (stderr, "CPXNETfreeprob failed, error code %d.\n", status);
      }
   }

   /* Free up the problem as allocated by CPXcreateprob, if necessary */

   if ( lp != NULL ) {
      CPXfreeprob (env, &lp);
      if ( status ) {
         fprintf (stderr, "CPXfreeprob failed, error code %d.\n", status);
      }
   }

   /* Free up the CPLEX environment, if necessary */

   if ( env != NULL ) {
      status = CPXcloseCPLEX (&env);

      /* Note that CPXcloseCPLEX produces no output,
         so the only way to see the cause of the error is to use
         CPXgeterrorstring.  For other CPLEX routines, the errors will
         be seen if the CPX_PARAM_SCRIND indicator is set to CPX_ON. */

      if ( status ) {
         char  errmsg[1024];
         fprintf (stderr, "Could not close CPLEX environment.\n");
         CPXgeterrorstring (env, status, errmsg);
         fprintf (stderr, "%s", errmsg);
      }
   }
     
   return (status);

}  /* END main */