# TOMNET  
# REGISTER (TOMNET)
# LOGIN  
# myTOMNET
TOMLAB LOGO

« Previous « Start » Next »

5  LPCON Problem

When solving a problem with a linear objective and nonlinear constraints there is no need to explicitly code the gradient or Hessian since these are implicitly given (the gradient is a constant array and the Hessian is all zeros). TOMNET automatically supplies these when inheriting from the linear problem class.

The linear constrained nonlinear programming problem is defined as:

 
min
x
f(x) = dT x
   
s/t
xL x xU
bL A x bU
cL c(x) cU
    (7)
where x, xL, xU, d ∈ Rn, f(x) ∈ R, A ∈ Rm1 × n, bL,bU ∈ Rm1 and cL,c(x),cU ∈ Rm2.

The solution quickguide/lpconQG/lpconQG.sln defines an example problem in TOMNET.
using System;
using TOMNET;

namespace TOMNET
{
  /// <summary>
  /// Quick guide class for linear problem
  /// with both linear and nonlinear constraints.
  /// </summary>
  public class lpconQG : LinearProblem
  {
    /// <summary>
    /// Constructor for Quick Guide Example for a linear
    /// problem with both linear and nonlinear constraints.
    /// </summary>
    /// <param name="n">Number of variables.</param>
    /// <param name="mLin">Number of linear constraints.</param>
    /// <param name="mNonLin">Number of nonlinear constraints.</param>
    /// <param name="c">Linear goal function.</param>
    /// <param name="A">Linear constraints (row-based).</param>
    /// <param name="b_L">Lower limits of linear constraints.</param>
    /// <param name="b_U">Upper limits of linear constraints.</param>
    /// <param name="x_0">Initial point.</param>
    /// <param name="x_L">Lower limits of variables.</param>
    /// <param name="x_U">Upper limits of variables.</param>
    /// <param name="c_L">Lower limits of nonlinear constraints.</param>
    /// <param name="c_U">Upper limits of nonlinear constraints.</param>
    /// <param name="Name">Name of problem</param>
    public lpconQG(int n, int mLin, int mNonLin, double[] c,
      double[] A,  double[] b_L, double[] b_U, double[] x_0,
      double[] x_L, double[] x_U, double[] c_L, double[] c_U,
      String Name) : base(c, A, b_L, b_U, x_L, x_U, x_0, Name,
      double.NegativeInfinity, null, null)
    {
      //
      // Nonlinear constraints.
      //
      this.mNonLin = mNonLin;
      this.c_L = new double[mNonLin];
      this.c_U = new double[mNonLin];

      //
      // Setting the nonlinear constraint bounds.
      //
      c_L.CopyTo(this.c_L, 0);
      c_U.CopyTo(this.c_U, 0);

      //
      // Other parameters.
      //
      this.Name = Name;
    }

    /// <summary>
    /// Nonlinear constraints.
    /// </summary>
    /// <param name="c">Nonlinear constraints in x.</param>
    /// <param name="x">The decision variables.</param>
    public override void c(double[] c, double[] x)
    {
      if (x[0] == 0 && x[1] == 0)
      {
        c[0] = 1.0;
      }
      else
      {
        c[0] = Math.Pow(x[0] * x[2] + x[1] * x[3], 2) /
          (Math.Pow(x[0], 2) + Math.Pow(x[1], 2)) -
          Math.Pow(x[2], 2) - Math.Pow(x[3], 2);
      }
    }

    /// <summary>
    /// Jacobian of nonlinear constraints.
    /// </summary>
    /// <param name="Jac">Jacobian of nonlinear constraints.</param>
    /// <param name="x">The decision variables.</param>
    public override void dc(Jacobian Jac, double[] x)
    {
      double h1 = Math.Pow(x[0], 2) + Math.Pow(x[1], 2);
      double h2 = x[0] * x[2] + x[1] * x[3];

      if (h1 == 0)
      {
        Jac[0, 0] = double.PositiveInfinity;
        Jac[0, 1] = double.PositiveInfinity;
        Jac[0, 2] = double.PositiveInfinity;
        Jac[0, 3] = double.PositiveInfinity;
      }
      else
      {
        Jac[0,0] = 2* h2 * x[2]/h1 - 2 * x[0] * Math.Pow(h2/h1, 2);
        Jac[0,1] = 2* h2 * x[3]/h1 - 2 * x[1] * Math.Pow(h2/h1, 2);
        Jac[0,2] = 2* h2 * x[0]/h1 - 2 * x[2];
        Jac[0,3] = 2* h2 * x[1]/h1 - 2 * x[3];
      }
    }

    /// <summary>
    /// Testprogram for lpconQG.
    /// </summary>
    static void Main()
    {
      //
      // For use in bounds.
      //
      double Inf = double.PositiveInfinity;

      //
      // Number of decision variables, linear and nonlinear
      // constraints, and name of the problem.
      //
      const int mLin = 3;
      const int mNonLin = 1;
      const int n = 4;
      string Name = "lpconQG";

      //
      // Linear Constraints and the lower and upper bounds.
      //
      double[] A = new double[n * mLin] { 1, 0, -1, 0, 0, 1, 0, -1, 0,
        0, 1, -1 };
      double[] b_L = new double[mLin] { 1, 1, 0 };
      double[] b_U = new double[mLin] { Inf, Inf, Inf };

      //
      // Lower and upper nonlinear constraint bounds.
      //
      double[] c_L = new double[mNonLin] { -1 };
      double[] c_U = new double[mNonLin] { -1 };

      //
      // Lower and upper bounds for decision variables as well
      // as the starting point for the solver.
      //
      double[] x_0 = new double[n] { 1, 0, 2, 0 };
      double[] x_L = new double[n] { -Inf, -Inf, -Inf, 1 };
      double[] x_U = new double[n] { 100, 100, 100, 100 };

      //
      // Entries for linear objective function.
      //
      double[] c = new double[n] { 3, 2, 0, 0 };

      //
      // Create a problem, solver and result instance.
      //
      lpconQG Prob = new lpconQG(n, mLin, mNonLin, c, A, b_L, b_U,
        x_0, x_L, x_U, c_L, c_U, Name);
      SNOPT solver = new SNOPT();
      Result result;

      //
      // Define a print file for SNOPT.
      //
      string printfilename = "SnoptlpconQP.txt";
      solver.Options.PrintFile = printfilename;

      //
      // Solve the problem.
      //
      solver.Solve(Prob, out result);

      //
      // Get the solution results.
      //
      double[] solution = result.x_k;
      double objective = result.f_k;

      //
      // Display the solution on the console.
      //
      Console.WriteLine(" * * * * * * * *");
      Console.WriteLine(" * Solved " + Prob.Name);
      Console.WriteLine(" * Printfile: " + printfilename);
      Console.WriteLine(" * Objective: {0}", objective);
      Console.WriteLine(" * Solution");
      Console.WriteLine("        x_L[i] <=     x_k[i] <=     x_U[i]");
      for (int i = 0; i < Prob.N; i++)
      {
        Console.WriteLine("    {0,10:g3} <= {1,10:g3} <= {2,10:g3} ",
          Prob.x_L[i], result.x_k[i], Prob.x_U[i]);
      }

      Console.WriteLine(" * Linear constraints");
      double[] Ax = Prob.A.Evaluate(result.x_k);
      Console.WriteLine("        b_L[i] <=   (A*x)[i] <=     b_U[i]");
      for (int i = 0; i < Prob.mLin; i++)
      {
        Console.WriteLine("    {0,10:g3} <= {1,10:g3} <= {2,10:g3}",
          Prob.A.GetLowerBound(i), Ax[i], Prob.A.GetUpperBound(i));
      }

      Console.WriteLine(" * Nonlinear constraint");
      Console.WriteLine("        c_L[i] <=      cx[i] <=     b_U[i]");
      double[] cx = new double[Prob.mNonLin];
      Prob.c(cx, result.x_k);
      for (int i = 0; i < Prob.mNonLin; i++)
      {
        Console.WriteLine("    {0,10:g3} <= {1,10:g3} <= {2,10:g3}",
          Prob.c_L[i], cx[i], Prob.c_U[i]);
      }
    }
  }
}
Observe that the code defines two functions that are used in the callback from the solvers. The d2c function is currently not implemented.
  c:   Nonlinear constraint vector
  dc:  Nonlinear constraint gradient matrix
  d2c: The second part of the Hessian to the Lagrangian
       function for the nonlinear constraints.
The lpconQG.sln  may be opened by a suitable editor and compiled to an exe file. When running the executable from a command prompt the following output results are displayed:

« Previous « Start » Next »