![]() | |||||||||||||
| |||||||||||||
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.
Source Files By clicking on a file name, a preview is opened at the bottom of this page.
PolygonObjects.cpp // (c) 2024-2024 Fair Isaac Corporation /** * Maximize the area of a polygon of N vertices and a diameter of 1. The * position of vertices is indicated as (r,theta) coordinates where r denotes * the distance to the base point (vertex with number N) and theta the angle * from the x-axis. */ #ifdef _WIN32 // To get M_PI # define _USE_MATH_DEFINES #endif #include <cmath> #include <xpress.hpp> using namespace xpress; using namespace xpress::objects; using xpress::objects::utils::cos; using xpress::objects::utils::sin; using xpress::objects::utils::sum; // the number of vertices/sides of the polygon #define NSIDES 5 int main() { XpressProblem prob; // Output all messages. prob.callbacks.addMessageCallback(XpressProblem::console); /**** VARIABLES ****/ // r corresponds to the distance from the base point to vertex i auto r = prob.addVariables(NSIDES - 1).withName("r_%d").withUB(1.0).toArray(); // theta corresponds to the angle relative to the x-axis of vertex i auto theta = prob.addVariables(NSIDES - 1).withName("theta_%d").withUB(M_PI).toArray(); /**** OBJECTIVE ****/ // objective transfer column Variable objtransfercol = prob.addVariable(XPRS_MINUSINFINITY, XPRS_PLUSINFINITY, ColumnType::Continuous, "objTransferCol"); // Set objective: maximize area of the polygon: // r_i*r_j*sin(theta_i+1-theta_i)/2 Expression area = sum(NSIDES - 2, [&](auto i) { return r[i] * r[i + 1] * sin(theta[i + 1] - theta[i]) / 0.5; }); // To make the objective linear, just maximize the objtransfercol prob.setObjective(objtransfercol, ObjSense::Maximize); // Add the objective transfer row: area = objtransfercol prob.addConstraint(area == objtransfercol); /**** CONSTRAINTS ****/ // any two non-origin nodes should have a distance <= 1 to satisfy the // diameter for (int i = 0; i < NSIDES - 1; i++) { for (int j = i + 1; j < NSIDES - 1; j++) { // r_i^2 + r_j^2 - 2 * r_i * r_j * cos(theta_j - theta_i) <= 1 prob.addConstraint(r[i].square() + r[j].square() - 2 * r[i] * r[j] * cos(theta[j] - theta[i]) <= 1.0); } } // Ordering of the vertices: theta_i+1 >= theta_i prob.addConstraints(NSIDES - 2, [&](auto i) { return theta[i + 1] >= theta[i]; }); // Dump the problem to disk so that we can inspect it. prob.writeProb("polygon.lp", "lp"); // Solve to local optimality prob.controls.setNlpSolver(XPRS_NLPSOLVER_LOCAL); // Solve prob.optimize(); if (prob.attributes.getSolStatus() != SolStatus::Optimal && prob.attributes.getSolStatus() != SolStatus::Feasible) throw std::runtime_error("optimization failed with status " + to_string(prob.attributes.getSolStatus())); auto sol = prob.getSolution(); std::cout << "Objective: " << prob.attributes.getObjVal() << std::endl; // Print out the solution for (auto &var : r) { std::cout << var.getName() << ":" << var.getValue(sol) << " "; } std::cout << std::endl; for (auto &var : theta) { std::cout << var.getName() << ":" << var.getValue(sol) << " "; } std::cout << std::endl; return 0; }
| |||||||||||||
© Copyright 2025 Fair Isaac Corporation. |