Nonlinear Feasibility Problem

Find a point that satisfies several nonlinear constraints, taken from this MATLAB example

Problem Description

\[(y+x^2)^2+0.1y^2\leq1\]
\[y\leq\exp(-x)-3\]
\[y\leq x-4\]

Does any point \((x,y)\) satisfy all of the constraints?

Modules Importing

Import all necessary modules and add PyGRANSO src folder to system path.

[1]:
import time
import torch
from pygranso.pygranso import pygranso
from pygranso.pygransoStruct import pygransoStruct

Function Set-Up

Encode the optimization variables, and objective and constraint functions.

Note: please strictly follow the format of comb_fn, which will be used in the PyGRANSO main algortihm.

[2]:
device = torch.device('cpu')

# variables and corresponding dimensions.
var_in = {"x": [1,1],"y": [1,1]}


def comb_fn(X_struct):
    x = X_struct.x
    y = X_struct.y
    # constant objective function
    f = 0*x+0*y

    # inequality constraint
    ci = pygransoStruct()
    ci.c1 = (y+x**2)**2+0.1*y**2-1
    ci.c2 = y - torch.exp(-x) - 3
    ci.c3 = y-x+4

    # equality constraint
    ce = None

    return [f,ci,ce]

User Options

Specify user-defined options for PyGRANSO

[3]:
opts = pygransoStruct()
opts.torch_device = device
opts.print_frequency = 1
# All the user-provided data (vector/matrix/tensor) must be in torch tensor format.
# As PyTorch tensor is single precision by default, one must explicitly set `dtype=torch.double`.
# Also, please make sure the device of provided torch tensor is the same as opts.torch_device.
opts.x0 = 0 * torch.ones((2,1)).to(device=device, dtype=torch.double)

Main Algorithm

[4]:
start = time.time()
soln = pygranso(var_spec = var_in,combined_fn = comb_fn,user_opts = opts)
end = time.time()
print("Total Wall Time: {}s".format(end - start))
print("PyGRANSO finds a feaible point:(%f,%f)"%(soln.final.x[0],soln.final.x[1]) )


╔═════ QP SOLVER NOTICE ════════════════════════════════════════════════════════════════════════╗
║  PyGRANSO requires a quadratic program (QP) solver that has a quadprog-compatible interface,  ║
║  the default is osqp. Users may provide their own wrapper for the QP solver.                  ║
║  To disable this notice, set opts.quadprog_info_msg = False                                   ║
╚═══════════════════════════════════════════════════════════════════════════════════════════════╝
═════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
PyGRANSO: A PyTorch-enabled port of GRANSO with auto-differentiation                                             ║
Version 1.2.0                                                                                                    ║
Licensed under the AGPLv3, Copyright (C) 2021-2022 Tim Mitchell and Buyun Liang                                  ║
═════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
Problem specifications:                                                                                          ║
 # of variables                     :   2                                                                        ║
 # of inequality constraints        :   3                                                                        ║
 # of equality constraints          :   0                                                                        ║
═════╦═══════════════════════════╦════════════════╦═════════════════╦═══════════════════════╦════════════════════╣
     ║ <--- Penalty Function --> ║                ║ Total Violation ║ <--- Line Search ---> ║ <- Stationarity -> ║
Iter ║    Mu    │      Value     ║    Objective   ║   Ineq   │  Eq  ║ SD │ Evals │     t    ║ Grads │    Value   ║
═════╬═══════════════════════════╬════════════════╬═════════════════╬═══════════════════════╬════════════════════╣
   0 ║ 1.000000 │  4.00000000000 ║  0.00000000000 ║ 4.000000 │   -  ║ -  │     1 │ 0.000000 ║     1 │ 1.414214   ║
   1 ║ 1.000000 │  3.40000000000 ║  0.00000000000 ║ 3.400000 │   -  ║ S  │     2 │ 2.000000 ║     2 │ 0.245323   ║
   2 ║ 1.000000 │  0.17527969143 ║  0.00000000000 ║ 0.175280 │   -  ║ S  │     2 │ 2.000000 ║     1 │ 0.128174   ║
   3 ║ 1.000000 │  0.00000000000 ║  0.00000000000 ║ 0.000000 │   -  ║ S  │     2 │ 2.000000 ║     1 │ 0.000000   ║
═════╩═══════════════════════════╩════════════════╩═════════════════╩═══════════════════════╩════════════════════╣
F = final iterate, B = Best (to tolerance), MF = Most Feasible                                                   ║
Optimization results:                                                                                            ║
═════╦═══════════════════════════╦════════════════╦═════════════════╦═══════════════════════╦════════════════════╣
   F ║          │                ║  0.00000000000 ║ 0.000000 │   -  ║    │       │          ║       │            ║
   B ║          │                ║  0.00000000000 ║ 0.000000 │   -  ║    │       │          ║       │            ║
  MF ║          │                ║  0.00000000000 ║ 0.000000 │   -  ║    │       │          ║       │            ║
═════╩═══════════════════════════╩════════════════╩═════════════════╩═══════════════════════╩════════════════════╣
Iterations:              3                                                                                       ║
Function evaluations:    7                                                                                       ║
PyGRANSO termination code: 0 --- converged to stationarity and feasibility tolerances.                           ║
═════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
Total Wall Time: 0.04715752601623535s
PyGRANSO finds a feaible point:(1.688660,-2.486619)