Example description
/* nag_opt_handle_add_vars (e04tac) Example Program.
 *
 * Copyright 2020 Numerical Algorithms Group.
 *
 * Mark 27.1, 2020.
 */

#include <nag.h>

int main(void) {

  /* This example program demonstrates how to edit an LP model using the
   * NAG Optimization Modeling Suite functionality
   *   We solve here 3 variants of a small LP model:
   *
   *     I/   max 2x1 + 4.5x2
   *            1.2x1 +  3x2 <= 1500
   *            6x1   + 10x2 <= 6000
   *            40x1  + 80x2  = 16000
   *            0 <= x1
   *            0 <= x2 <= 100
   *
   *     II/ A variable is added
   *          max 2x1 + 4.5x2 + 7x3
   *            1.2x1 + 3x2 + 5x3   <= 1500
   *            6x1  + 10x2 + 12x3  <= 6000
   *            40x1 + 80x2 + 120x3  = 16000
   *            0 <= x1
   *            0 <= x2 <= 100
   *            0 <= x3 <= 50
   *
   *     III/ A linear constraint is added
   *          max 2x1 + 4.5x2 + 7x3
   *            1.2x1 + 3x2 + 5x3   <= 1500
   *            6x1  + 10x2 + 12x3  <= 6000
   *            40x1 + 80x2 + 120x3  = 16000
   *                    x2  +   x3  <= 100
   *            0 <= x1
   *            0 <= x2 <= 100
   *            0 <= x3 <= 50
   */

  const double infbnd = 1.0e20;
  const char *cmdstr = "pinfo";
  Integer exit_status = 0;
  Integer nvar, nclin, nnza, nnzu, i, idlc, ioflag, liarr;
  Integer *irowa = 0, *icola = 0;
  Integer pinfo[100];
  double *x = 0, *xl = 0, *xu = 0, *bla = 0, *bua = 0, *a = 0, *cvec = 0,
    *ulag = 0;
  double rinfo[100], stats[100], u[1];
  void *handle = 0;
  Nag_Comm comm;
  NagError fail;

  printf("nag_opt_handle_add_vars (e04tac) Example Program Results\n\n");
  fflush(stdout);

  nvar = 2;
  nclin = 3;
  nnza = 6;
  /* Allocate memory */
  if (!(irowa = NAG_ALLOC(nnza, Integer)) ||
      !(icola = NAG_ALLOC(nnza, Integer)) ||
      !(cvec = NAG_ALLOC(nvar, double)) || !(a = NAG_ALLOC(nnza, double)) ||
      !(bla = NAG_ALLOC(nclin, double)) || !(bua = NAG_ALLOC(nclin, double)) ||
      !(xl = NAG_ALLOC(nvar, double)) || !(xu = NAG_ALLOC(nvar, double)) ||
      !(x = NAG_ALLOC(nvar + 1, double))) {
    printf("Allocation failure\n");
    exit_status = -1;
    goto END;
  }

  /* Create the problem handle
   * nag_opt_handle_init (e04rac). */
  nag_opt_handle_init(&handle, nvar, NAGERR_DEFAULT);

  /* Define the objective function
   * nag_opt_handle_set_linobj (e04rec) */
  cvec[0] = 2.0;
  cvec[1] = 4.5;
  nag_opt_handle_set_linobj(handle, nvar, cvec, NAGERR_DEFAULT);

  /* nag_opt_handle_set_simplebounds (e04rhc)
   * Define bounds on the variables */
  xl[0] = 0.0;
  xl[1] = 0.0;
  xu[0] = infbnd;
  xu[1] = 100.0;
  nag_opt_handle_set_simplebounds(handle, nvar, xl, xu, NAGERR_DEFAULT);

  /* nag_opt_handle_set_linconstr (e04rjc)
   * Define linear constraints */
  idlc = 0;
  bla[0] = -infbnd;
  bla[1] = -infbnd;
  bla[2] = 16000.0;
  bua[0] = 1500.0;
  bua[1] = 6000.0;
  bua[2] = 16000.0;
  for (i = 0; i < nnza / 2; i++) {
    irowa[2 * i] = i + 1;
    irowa[2 * i + 1] = i + 1;
    icola[2 * i] = 1;
    icola[2 * i + 1] = 2;
  }
  a[0] = 1.2;
  a[1] = 3.0;
  a[2] = 6.0;
  a[3] = 10.0;
  a[4] = 40.0;
  a[5] = 80.0;
  nag_opt_handle_set_linconstr(handle, nclin, bla, bua, nnza, irowa, icola, a,
                               &idlc, NAGERR_DEFAULT);

  /* nag_opt_handle_opt_set (e04zmc)
   * Set optional parameters */
  nag_opt_handle_opt_set(handle, "Task = Max", NAGERR_DEFAULT);
  nag_opt_handle_opt_set(handle, "Print Level = 1", NAGERR_DEFAULT);
  nag_opt_handle_opt_set(handle, "Print options = No", NAGERR_DEFAULT);
  nag_opt_handle_opt_set(handle, "Print Solution = X", NAGERR_DEFAULT);

  printf("Solve the first LP\n\n");
  fflush(stdout);

  /* nag_opt_handle_solve_lp_ipm (e04mtc)
   * Solve the model */
  nnzu = 0;
  nag_opt_handle_solve_lp_ipm(handle, nvar, x, nnzu, u, rinfo, stats, NULL,
                              &comm, NAGERR_DEFAULT);

  /* Second variant: add a variable */
  /* nag_opt_handle_add_vars (e04tac)
   * Add the third variable to the handle */
  nag_opt_handle_add_vars(handle, 1, &nvar, NAGERR_DEFAULT);

  /* nag_opt_handle_set_bound (e04tdc)
   * The new variable is nonnegative */
  nag_opt_handle_set_bound(handle, "variable", nvar, 0.0, 50.0, NAGERR_DEFAULT);

  /* nag_opt_handle_set_linobj_coeff (e04tec)
   * Set the objective coefficient */
  nag_opt_handle_set_linobj_coeff(handle, 3, 7.0, NAGERR_DEFAULT);

  /* nag_opt_handle_set_linconstr_coeff (e04tjc)
   * Add linear constraints coefficients */
  nag_opt_handle_set_linconstr_coeff(handle, 1, 3, 5.0, NAGERR_DEFAULT);
  nag_opt_handle_set_linconstr_coeff(handle, 2, 3, 12.0, NAGERR_DEFAULT);
  nag_opt_handle_set_linconstr_coeff(handle, 3, 3, 120.0, NAGERR_DEFAULT);

  printf("\nThe new variable has been added, solve the handle again\n\n");
  fflush(stdout);

  /* Solve the altered problem */
  nag_opt_handle_solve_lp_ipm(handle, nvar, x, nnzu, u, rinfo, stats, NULL,
                              &comm, NAGERR_DEFAULT);

  /* Add a linear constraint */
  nclin = 1;
  bla[0] = -infbnd;
  bua[0] = 100.0;
  nnza = 2;
  irowa[0] = 1;
  irowa[1] = 1;
  icola[0] = 2;
  icola[1] = 3;
  a[0] = 1.0;
  a[1] = 1.0;
  idlc = 0;
  nag_opt_handle_set_linconstr(handle, nclin, bla, bua, nnza, irowa, icola, a,
                               &idlc, NAGERR_DEFAULT);

  printf("\nThe new constraint has been added, solve the handle again\n\n");
  fflush(stdout);

  /* nag_opt_handle_set_get_integer (e04rwc)
   * Query the problem sizes to request the Lagrangian multipliers for the last
   * solve */
  ioflag = 1;
  liarr = 100;
  nag_opt_handle_set_get_integer(handle, cmdstr, ioflag, &liarr, pinfo, NAGERR_DEFAULT);
  nnzu = pinfo[10];
  if (!(ulag = NAG_ALLOC(nnzu, double))) {
    printf("Allocation failure\n");
    exit_status = -1;
    goto END;
  }

  /* Solve the third version of the problem */
  INIT_FAIL(fail);
  nag_opt_handle_solve_lp_ipm(handle, nvar, x, nnzu, ulag, rinfo, stats, NULL,
                              &comm, &fail);

END:
  /* nag_opt_handle_free (e04rzc).
   * Destroy the problem handle and deallocate all the memory. */
  if (handle)
    nag_opt_handle_free(&handle, NAGERR_DEFAULT);
  NAG_FREE(cvec);
  NAG_FREE(irowa);
  NAG_FREE(icola);
  NAG_FREE(a);
  NAG_FREE(bla);
  NAG_FREE(bua);
  NAG_FREE(xl);
  NAG_FREE(xu);
  NAG_FREE(x);
  NAG_FREE(ulag);
  return exit_status;
}