FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserPrevious exampleNext example

Polygon - Defining nonlinear constraints

Description
Maximize the area of polygon of N vertices and diameter of 1. This example demonstrates how to build nonlinear formulae from strings and token sequences.

Difficulty rating: 3 (intermediate)

polygonobjects_dnet.zip[download all files]

Source Files
By clicking on a file name, a preview is opened at the bottom of this page.
PolygonObjects.cs[download]
PolygonObjects.csproj[download]





PolygonObjects.cs

// (c) 2023-2026 Fair Isaac Corporation

using System;
using Optimizer;
using Optimizer.Objects;
using static Optimizer.Objects.Utils;


namespace XpressExamples
{
    /// <summary>
    /// Code example showing how to build nonlinear formulae
    /// </summary>
    /// <remarks>
    ///   Maximize the area of polygon of N vertices and diameter of 1
    ///   The position of vertices is indicated as (rho,theta) coordinates
    ///   where rho denotes the distance to the base point
    ///   (vertex with number N - 1) and theta the angle from the x-axis.
    ///
    ///   Demonstrating how to build nonlinear formulae from strings and token sequences
    ///
    /// <code>
    ///     Variables:
    ///
    ///     r     : 0..N-1   ! Distance of vertex from the base point
    ///     theta : 0..N-1   ! Angle from x-axis
    ///
    ///     Objective:
    ///         (sum (i in 1..N-2) (r(i)*r(i-1)*sin(theta(i)-theta(i-1)))) * 0.5
    ///
    ///     Constraints:
    ///         Vertices in increasing degree order:
    ///         theta(i) >= theta(i-1) +.0001  : i = 1..N-2
    ///         Boundary conditions:
    ///         theta(N-1) <= Pi
    ///         0.1 <= r(i) <= 1   : i = 0..N-2
    ///         Third side of all triangles <= 1
    ///         r(i)^2 + r(j)^2 - r(i)*r(j)*2*cos(theta(j)-theta(i)) <= 1    : i in 0..N-3, j in i..N-2
    /// </code>
    /// </remarks>
    public class PolygonObjects
    {
        /// the number of vertices/sides of the polygon
        const int NSIDES = 5;

        public static void Main(string[] args)
        {

            using (XpressProblem prob = new XpressProblem())
            {
                // Output all messages.
                prob.callbacks.AddMessageCallback(DefaultMessageListener.Console);

                /****VARIABLES****/
                /// THETA corresponds to the angle relative to the x-axis of vertex i
                Variable[] theta = prob.AddVariables(NSIDES - 1)
                    .WithType(ColumnType.Continuous)
                    .WithUB(Math.PI)
                    .WithName("theta_{0}")
                    .ToArray();

                /// R corresponds to the distance from the base point to vertex i
                Variable[] r = prob.AddVariables(NSIDES - 1)
                    .WithType(ColumnType.Continuous)
                    .WithLB(0.1)
                    .WithUB(1.0)
                    .WithName("r_{0}")
                    .ToArray();

                /// Objective transfer column
                Variable objective = prob.AddVariable(
                    XPRS.MINUSINFINITY,
                    XPRS.PLUSINFINITY,
                    ColumnType.Continuous,
                    "objective");

                Expression[] area = new Expression[NSIDES - 2];
                /// Objective transfer row
                for (int i = 0; i < NSIDES - 2; i++)
                {
                    area[i] = 0.5 * r[i] * r[i + 1] * Sin(theta[i + 1] - theta[i]);
                }
                prob.AddConstraint(Sum(area).Eq(objective));

                /// Set the objective
                prob.SetObjective(objective, ObjSense.Maximize);

                /// The distance between any pair of points is at most 1
                for (int i = 0; i < NSIDES - 1; i++)
                {
                    for (int j = i + 1; j < NSIDES - 1; j++)
                    {
                        prob.AddConstraint(r[i] * r[i] + r[j] * r[j] - 2.0 * r[i] * r[j] * Cos(theta[j] - theta[i]) <= 1.0);
                    }
                }

                /// Ordering the vertices: theta_i+1 >= theta_i
                prob.AddConstraints(NSIDES - 2,
                        (i) => Sum(theta[i + 1], theta[i].Mul(-1)).Geq(0.0));

                /// Optimize
                prob.Optimize("s");
                if (prob.SolStatus != Optimizer.SolStatus.Optimal &&
                        prob.SolStatus != Optimizer.SolStatus.Feasible)
                    throw new Exception("optimization failed with status " + prob.SolStatus);
                double[] sol = prob.GetSolution();
                /* Print out the solution */
                Console.WriteLine("Objective: {0:f4}", prob.ObjVal);
                foreach (Variable v in r)
                {
                    Console.Write("{0}: {1:f4}\n", v.GetName(), v.GetValue(sol));
                }
                Console.WriteLine();
                foreach (Variable v in theta)
                {
                    Console.Write("{0}: {1:f4}\n", v.GetName(), v.GetValue(sol));
                }
                Console.WriteLine();
            }
        }
    }
}

Back to examples browserPrevious exampleNext example