{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# **Inscribed square problem with Xpress NonLinear and Xpress Global**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "***inscribed_square.ipynb***\n",
    "\n",
    "This example shows how to use FICO&reg; Xpress NonLinear (SLP) or FICO&reg; Xpress Global to solve an instance of the inscribed square problem.\n",
    "\n",
    "<!--*This example requires a license for the FICO&reg; Xpress Global solver. Click on [this link](https://www.fico.com/en/fico-xpress-trial-and-licensing-options) for more information about trial and licensing options.*-->\n",
    "\n",
    "&copy; Copyright 2025 Fair Isaac Corporation\n",
    "\n",
    "Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.\n",
    " \n",
    "Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n",
    "\n",
    "This example uses FICO&reg; Xpress software. By running it, you agree to the Community License terms of the [Xpress Shrinkwrap License Agreement](https://www.fico.com/en/shrinkwrap-license-agreement-fico-xpress-optimization-suite-on-premises) with respect to the FICO&reg; Xpress software. See the [licensing options](https://www.fico.com/en/fico-xpress-trial-and-licensing-options) overview for additional details and information about obtaining a paid license."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Install the xpress package\n",
    "%pip install -q xpress"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The inscribed square problem, also known as the square peg problem or the Toeplitz' conjecture, is an unsolved question in geometry: Does every plane simple closed curve contain all four vertices of some square? The problem was proposed by [Otto Toeplitz in 1911](https://en.wikipedia.org/wiki/Inscribed_square_problem).\n",
    "The next example is a special instance of the problem, and computes a **maximal inscribing square** for the curve defined by: \n",
    "\n",
    "$$(\\sin(t) \\cdot \\cos(t), \\sin(t) \\cdot t), t \\in [-\\pi,\\pi]$$\n",
    "\n",
    "[Source in MINLPLIB](https://www.minlplib.org/inscribedsquare01.html)\n",
    "\n",
    "The problem is formulated using decision variables $t_i, \\forall i = 1..4$, with values in the range $[-\\pi,\\pi]$, corresponding to the four values of the parameter $t$. Then, $x$ and $y$ are the coordinates of the first corner of the square, while ($a, b$) is a vector pointing to a second vertex. The remaining vertices are given by combining $x, y, a, b$. The length of the vector ($a, b$) is exactly the side length of the square, which we aim at maximizing.\n",
    "\n",
    "The first two constraints define $x$ and $y$ as the coordinates of the first point:\n",
    "$$\n",
    "\\begin{array}{llll}\n",
    "& \\qquad \\sin(t_1) \\cdot \\cos(t_1) = x \\\\\n",
    "& \\qquad \\sin(t_1) \\cdot t_1 = y \\\\\n",
    "\\end{array}\n",
    "$$\n",
    "\n",
    "The next two constraints define the coordinates of the second vertex by adding the pointed vector ($a$, $b$) to the first point ($x$, $y$):\n",
    "$$\n",
    "\\begin{array}{llll}\n",
    "& \\qquad \\sin(t_2) \\cdot \\cos(t_2) = x + a\\\\\n",
    "& \\qquad \\sin(t_2) \\cdot t_2 = y + b \\\\\n",
    "\\end{array}\n",
    "$$\n",
    "\n",
    "The remaining four constraints make sure that we define a square by defining its remaining two vertices as combinations of ($x$, $y$) and the vector ($a$, $b$):\n",
    "$$\n",
    "\\begin{array}{llll}\n",
    "& \\qquad \\sin(t_3) \\cdot \\cos(t_3) = x - b \\\\\n",
    "& \\qquad \\sin(t_3) \\cdot t_3 = y + a \\\\\n",
    "& \\qquad \\sin(t_4) \\cdot \\cos(t_4) = x + a - b \\\\\n",
    "& \\qquad \\sin(t_4) \\cdot t_4 = y + a + b \\\\\n",
    "\\end{array}\n",
    "$$\n",
    "\n",
    "The objective is to maximize the length of one (or each) side of the square:\n",
    "$$\n",
    "\\begin{array}{llll}\n",
    "& \\qquad \\max a^2 + b^2\n",
    "\\end{array}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import xpress as xp\n",
    "import math\n",
    "import numpy as np\n",
    "from matplotlib import pyplot as plt\n",
    "from collections import namedtuple\n",
    "\n",
    "p = xp.problem()\n",
    "\n",
    "# Add the variables, note that we force the first point to have positive x- and y-coordinates to break symmetry.\n",
    "x1 = p.addVariable(name='x1', lb=-math.pi, ub=math.pi)\n",
    "x2 = p.addVariable(name='x2', lb=-math.pi, ub=math.pi)\n",
    "x3 = p.addVariable(name='x3', lb=-math.pi, ub=math.pi)\n",
    "x4 = p.addVariable(name='x4', lb=-math.pi, ub=math.pi)\n",
    "x5 = p.addVariable(name='x5')\n",
    "x6 = p.addVariable(name='x6')\n",
    "x7 = p.addVariable(name='x7')\n",
    "x8 = p.addVariable(name='x8')\n",
    "\n",
    "# Set initial values for the local solvers.\n",
    "p.nlpSetInitVal([x1, x2, x4, x5, x6, x7, x8], [-math.pi, -math.pi/2, math.pi/2, 0, 0, 1, 1])\n",
    "\n",
    "# The first two constraints define x5 and x6 as the coordinates of the first point.\n",
    "p.addConstraint(xp.sin(x1) * xp.cos(x1) - x5 == 0)\n",
    "p.addConstraint(xp.sin(x1) * x1 - x6 == 0)\n",
    "# The next two constraints define x7 and x8 as the pointed vector from the first to the second point.\n",
    "p.addConstraint(xp.sin(x2) * xp.cos(x2) - x5 -x7 == 0)\n",
    "p.addConstraint(xp.sin(x2) * x2 - x6 -x8 == 0)\n",
    "# The remaining four constraints make sure that we define a square by comparing vectors between the remaining points.\n",
    "p.addConstraint(xp.sin(x3) * xp.cos(x3) - x5 + x8 == 0)\n",
    "p.addConstraint(xp.sin(x3) * x3 - x6 - x7 == 0)\n",
    "p.addConstraint(xp.sin(x4) * xp.cos(x4) - x5 - x7 + x8 == 0)\n",
    "p.addConstraint(xp.sin(x4) * x4 - x6 - x7 - x8 == 0)\n",
    "\n",
    "# The objective is to maximize the length of one (or each) side of the square.\n",
    "p.setObjective(x7**2 + x8**2, sense=xp.maximize)\n",
    "\n",
    "# Choose between solving with a local or global solver.\n",
    "p.controls.nlpsolver = xp.constants.NLPSOLVER_LOCAL\n",
    "# Choose between solving with SLP or Knitro.\n",
    "p.controls.localsolver = xp.constants.LOCALSOLVER_XSLP\n",
    "\n",
    "p.optimize()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The specific nonlinear solver can be chosen using the [NLPSOLVER](https://www.fico.com/fico-xpress-optimization/docs/latest/solver/nonlinear/HTML/XSLP_NLPSOLVER.html) control:\n",
    "  - Setting a value of \"1\" will invoke a local solver, with it being either SLP or Knitro (**if a license is available. The community license does not include Knitro**). \n",
    "  - The control defaults to -1, which has Xpress choose the most appropriate solver. If there are user functions or multi-start jobs, or if there is no license available for Xpress Global, a local solver will be called. In all other cases, Xpress Global will be used to solve the problem.\n",
    "\n",
    "If a local solve is invoked, the [LOCALSOLVER](https://www.fico.com/fico-xpress-optimization/docs/latest/solver/nonlinear/HTML/XSLP_SOLVER.html) control specify if either SLP or Knitro should be used by setting the control to \"1\" or \"2\" respectively. For convex QPs, setting the value to \"2\" will set Xpress Optimizer to solve the problem. By default (-1), an automatic selection is made based on model characteristics and solver availability.\n",
    "\n",
    "By running the previous code cell below with the NLPSOLVER control equal to 1, SLP or Knitro will be called and the problem is solved to local optimality. This can be confirmed by running the code cell again with NLPSOLVER equal to 2, which finds a larger (maximal) square.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "solution: x1: -2.7325955676531377 , x2: -1.9797934127315524 , x3: 2.7325955676531377 , x4: 1.9797934127315524 , x5: 0.3648880884756273 , x6: 1.0867243481340831 , x7: 0.0 , x8: 0.7297761769512545\n"
     ]
    }
   ],
   "source": [
    "# Visualize solution.\n",
    "Point = namedtuple('Point', 'x y')\n",
    "\n",
    "def get_coords(t):\n",
    "\n",
    "  x = np.sin(t) * np.cos(t)\n",
    "  y = np.sin(t) * t\n",
    "  return Point(x, y)\n",
    "\n",
    "# Below code approximates the graph of the function.\n",
    "t = np.arange(-math.pi, math.pi, 0.01)\n",
    "xs = np.sin(t) * np.cos(t)\n",
    "ys = np.sin(t) * t\n",
    "\n",
    "# Compute the x- and y-coordinates of the four vertices of the square.\n",
    "v1 = get_coords(p.getSolution(x1))\n",
    "v2 = get_coords(p.getSolution(x2))\n",
    "v3 = get_coords(p.getSolution(x3))\n",
    "v4 = get_coords(p.getSolution(x4))\n",
    "\n",
    "# Plot the graph and the square.\n",
    "fig, ax = plt.subplots()\n",
    "cells = ax.plot(xs, ys)\n",
    "plt.plot([v1.x, v2.x], [v1.y, v2.y], 'ro-')\n",
    "plt.plot([v2.x, v4.x], [v2.y, v4.y], 'ro-')\n",
    "plt.plot([v4.x, v3.x], [v4.y, v3.y], 'ro-')\n",
    "plt.plot([v3.x, v1.x], [v3.y, v1.y], 'ro-')\n",
    "\n",
    "ax.set_aspect('equal', adjustable='box')\n",
    "\n",
    "plt.show()\n",
    "\n",
    "# Print the solution values for variables.\n",
    "print('solution: x1:', p.getSolution(x1), ', x2:', p.getSolution(x2), ', x3:', p.getSolution(x3), ', x4:', p.getSolution(x4), \n",
    "      ', x5:', p.getSolution(x5), ', x6:', p.getSolution(x6), ', x7:', p.getSolution(x7), ', x8:', p.getSolution(x8))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "xpress9.8 (3.12.9)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
