Initializing help system before first use

Basic formulation

Nonlinear capabilities in Mosel are provided by the mmxnlp module. Please refer to the module documentation for more details. This chapter provides a short introduction only.

The model uses the Mosel module mmxnlp which contains the extensions required for modeling general non-linear expressions. This automatically loads the mmxprs module, so there is no need to include this explicitly as well.

model "Polygon"
uses "mmxnlp"

We can design the model to work for any number of sides, so one way to do this is to set the number of sides of the polygon as a parameter.

parameters
  N=5
end-parameters

The meanings of most of these declarations will become apparent as the modeling progresses.

declarations
  area: nlctr
  rho: array(1..N) of mpvar
  theta: array(1..N) of mpvar
  objdef: mpvar
  D: array(1..N,1..N) of nlctr
end-declarations
  • The distances are described as "rho", to distinguish them from the default names for the rows in the generated matrix (which are R1, R2, etc).
  • The types nlctr (nonlinear constraint) are defined by the mmxnlp module.
area := sum(i in 2..N-1) (rho(i) * rho(i-1) * sin(theta(i)-theta(i-1)))*0.5

This uses the normal Mosel sum function to calculate the area. Notice that the formula is written in essentially the same way as normal, including the use of the sin function. Because the argument to the function is not a constant, Mosel will not try to evaluate the function yet; instead, it will be evaluated as part of the optimization process.

area is a Mosel object of type nlctr.

objdef = area
objdef is_free

What we really want to do is to maximize area. However, although Xpress NonLinear is happy in principle with a non-linear objective function, the Xpress Optimizer is not, unless it is handled in a special way. Xpress NonLinear therefore imposes the requirement that the objective function itself must be linear. This is not really a restriction, because – as in this case – it is easy to reformulate a non-linear objective function as an apparently linear one. Simply replace the function by a new mpvar and then maximize the value of the mpvar. In general, because the objective could have a positive or negative value, we make the variable free, so that it can take any value. In this example, we say:

objdef = area defining the variable objdef to be equal to the non-linear expression area
objdef is_free defining objdef to be a free variable
maximize(objdef) maximizing the linear objective

This is firstly setting the standard bounds on the variables rho and theta. To reduce problems with sides of zero length, we impose a minimum of 0.1 on rho(i) instead of the default minimum of zero.

forall (i in 1..N-1) do
  rho(i) >= 0.1
  rho(i) <= 1
  setinitval(rho(i), 4*i*(N+1-i)/((N+1)^2))
  setinitval(theta(i), M_PI*i/N)
end-do

We also give Xpress NonLinear initial values by using the setinitval procedure. The first argument is the name of the variable, and the second is the initial value to be used. The initial values for theta are divided equally between 0 and π. The initial values for rho are designed to go from 0 (when i=0 or N) to 1 (when i is about half way) and back.

forall (i in 1..N-2, j in i+1..N-1) do
  D(i,j) := rho(i)^2 + rho(j)^2 - rho(i)*rho(j)*2*cos(theta(j)-theta(i)) <lt/>= 1
end-do

This is creating the general constraints D(i,j) which constrain the other sides of the triangles to be ≤ 1.

These constraints could be made anonymous – that is, the assignment to an object of type nlctr could be omitted – but then it would not be possible to report the values.

forall (i in 2..N-1) do
  theta(i) >= theta(i-1) + 0.01
end-do

These anonymous constraints put the values of the theta variables in non-decreasing order. To avoid problems with triangles which have zero angles, we make each bearing at least 0.01 greater than its predecessor.

This is the boundary condition on the bearing of the final vertex.

theta(N-1) <= M_PI