Quantcast
Channel: Yet Another Math Programming Consultant
Viewing all articles
Browse latest Browse all 804

Another very small but very difficult global NLP model

$
0
0

The goal of this exercise is to fill a square area \([0,250]\times[0,100]\) with 25 circles. The model can choose the \(x\) and \(y\) coordinates of the center of each circle and the radius. So we have as variables \(\color{darkred}x_i\), \(\color{darkred}y_i\), and \(\color{darkred}r_i\). The circles placed inside the area should not overlap. The objective is to maximize the total area covered. 

A solution is:


The optimization model can look like: 


Non-convex Quadratic Model
     \[\begin{align} \max&\sum_i \color{darkblue}\pi\cdot\color{darkred}r_i^2 && &&\text{maximize covered area}\\ &(\color{darkred}x_i-\color{darkred}x_j)^2 + (\color{darkred}y_i-\color{darkred}y_j)^2 \ge (\color{darkred}r_i+\color{darkred}r_j)^2 && \forall i\lt j && \text{no overlap} \\ & \color{darkred}x_i-\color{darkred}r_i \ge 0 && && \text{stay inside area} \\ & \color{darkred}x_i+\color{darkred}r_i \le \color{darkblue}{\mathit{sizeX}} \\ & \color{darkred}y_i-\color{darkred}r_i \ge 0 \\ & \color{darkred}y_i+\color{darkred}r_i \le \color{darkblue}{\mathit{sizeY}} \\ & \color{darkred}r_i \le \color{darkred}r_{i-1} && \forall i\gt 1&& \text{optional symmetry breaker}\\ & \color{darkred}x_i \in [0,\color{darkblue}{\mathit{sizeX}}] && && \text{bounds} \\ &\color{darkred}y_i \in [0,\color{darkblue}{\mathit{sizeY}}] \\ & \color{darkred}r_i \in \left[0,\frac{\min(\color{darkblue}{\mathit{sizeX}},\color{darkblue}{\mathit{sizeY}})}{2}\right]\end{align}\]

The objective is simply maximizing the area covered by all circles. Actually, I reformulated this into an objective that measures the percentage of the covered area. The pairwise no-overlap constraints are defined over only \(i \lt j\) to prevent checking a pair of circles twice. The symmetry-breaking constraint reduces the size of the problem. Note that we have both a non-convex quadratic objective and a non-convex no-overlap constraint.

The model is small: 75 variables and 424 constraints. However, it is somewhat of a nightmare for global solvers. It is extremely difficult to prove optimality. We can find an excellent starting solution by using a simple multi-start algorithm with a local NLP solver. In fact, in this experiment, the multi-start algorithm found the best solution. The global solvers did not improve on this. 

The results are:

----    156 VARIABLE z.L                   =       91.183covered area (% of area)

----    162 PARAMETER results  

                   x           y           r

circle1      200.00050.00050.000
circle2       50.00050.00050.000
circle3      125.00028.12528.125
circle4      116.66777.77822.222
circle5      150.00087.50012.500
circle6       92.8579.1849.184
circle7      157.1439.1849.184
circle8      142.30860.5778.654
circle9        8.57991.4218.579
circle10     241.4218.5798.579
circle11     241.42191.4218.579
circle12       8.5798.5798.579
circle13      90.00092.0008.000
circle14     166.66794.4445.556
circle15     104.54553.7664.675
circle16      80.0004.5004.500
circle17     170.0004.5004.500
circle18       4.28920.7114.289
circle19     245.71120.7114.289
circle20       4.28979.2894.289
circle21     150.00070.8334.167
circle22      78.57195.9184.082
circle23     142.30873.0773.846
circle24     155.40521.2843.041
circle25       2.56672.6542.566


Conclusions


  • These models are very difficult for global solvers. 
  • This is a nice benchmark problem as we can scale it from very small to very large. In addition, humans can easily assess the quality of the solution by visual inspection of a plot. We can easily spot bad solutions. Even very small instances can be very tough to solve to proven optimality.
  • Multi-start NLP is quite effective in finding good solutions. 
  • GAMS support for multi-start NLP algorithms is limited and can be improved. We want to generate the model just once and use parallel execution. This use case would be a good candidate for the scenario solver Guss. It is inexplicable why this is not supported. 
  • The optional symmetry-breaking constraint is beneficial when using global solvers. Global solvers behave more like MIP solvers, where such constraints can be highly effective. A tiny 4 circle problem yielded the following timings:

     Without symmetry constraint:
                 313360 Nodes explored
                1968.00 Total time (wall s)

    With symmetry constraint:
                  25759 Nodes explored
                  86.00 Total time (wall s)
  •      
  • However, the symmetry constraint hurts when using the multi-start algorithm. Local solvers take more time to become feasible and, in general, find worse local optima. For the local search, it is better to turn off the symmetry constraint. To illustrate, here are the results of 100 trials with 10 circles:

    With symmetry constraint:
    ----    112 PARAMETER zbest                =       83.686  best objective

    Without symmetry constraint:
    ----    112 PARAMETER zbest                =       86.096  best objective

  • A solver like Baron has a built-in facility to perform a multi-start local search before it really starts working on the global problem. Here, I argue that it may be better to separate these phases.


Appendix: GAMS model




$onText

 

Place 25 circles (size is endogenous) on a [0,250]x[0,100] square area such that

circles don't overlap and the total area covered is maximized.

 

Very tough little non-convex NLP.

 

            Obj

MultiStart  91.183   (1015 trials, w/o symmetry constraint)

Baron       91.183   (no improvement, 1 hour, with symmetry breaker)

 

$offText

 

*-------------------------------------------------------------------

* size of problem

*-------------------------------------------------------------------

 

Set i 'circles' /circle1*circle25/;

alias (i,j);

 

set ij(i,j'compare circles i and j: only i<j';

ij(i,j) = ord(i) < ord(j);

 

scalars

  sizeX 'size of area' /250/

  sizeY 'size of area' /100/

;

 

*-------------------------------------------------------------------

* NLP Model

*-------------------------------------------------------------------

 

positive variables

   x(i'x-coordinate'

   y(i'y-coordinate'

   r(i'radius'

;

 

x.up(i) = sizeX;

y.up(i) = sizeY;

r.up(i) = min(sizeX,sizeY)/2;

 

variable 'covered area (% of area)';

 

equations

    cover  'calculate total area covered'

    no_overlap(i,j'circles cannot overlap'

    xlo(i'stay inside [0,250]'

    xup(i'stay inside [0,250]'

    ylo(i'stay inside [0,100]'

    yup(i'stay inside [0,100]'

    symmetry(i'symmetry breaker'

;

 

 

cover.. z =e= 100*sum(ipi*sqr(r(i))) / (sizeX*sizeY);

no_overlap(ij(i,j)).. sqr(x(i)-x(j)) + sqr(y(i)-y(j)) =g= sqr(r(i)+r(j));

xlo(i).. x(i) - r(i) =g= 0;

xup(i).. x(i) + r(i) =l= sizeX;

ylo(i).. y(i) - r(i) =g= 0;

yup(i).. y(i) + r(i) =l= sizeY;

symmetry(i-1) .. r(i) =l= r(i-1);

 

 

* improves logging of gap, but may slow things down

* (nl obj becomes a constraint)

z.up = 100;

 

 

model circlesw  'with symmetry' /all/ ;

model circleswo 'w/o symmetry' /circlesw - symmetry/ ;

 

 

*-------------------------------------------------------------------

* select algorithm

*-------------------------------------------------------------------

 

$set MultiStart 1

$set Global     1

 

 

*-------------------------------------------------------------------

multistart approach using local NLP solver

* best used without symmetry breaker

* we get a solution:  91.183 @ trial1015

*-------------------------------------------------------------------

 

$ifThen %MultiStart% == 1

 

set k /trial1*trial1015/;

option qcp = conopt;

parameter best(i,*) 'best solution';

scalar zbest 'best objective' /0/;

parameter trace(k) 'keep track of improvements';

circleswo.solprint = %solprint.Silent%;

circleswo.solvelink = 5;

loop(k,

     x.l(i) = uniform(10,sizeX-10);

     y.l(i) = uniform(10,sizeY-10);

     r.l(i) = uniform(10,40);

    

     solve circleswo maximizing z using qcp;

     if(z.l>zbest,

         zbest = z.l;

         best(i,'x') = x.l(i);

         best(i,'y') = y.l(i);

         best(i,'r') = r.l(i);

         trace(k) = z.l;

    );

 );

 

display zbest,best,trace;

 

* ugly code to sort on r so we can use symmetry constraint in

* subsequent solve.

set rem(i'remaining';

rem(i) = yes;

option strictSingleton = 0;

singleton set cur(i'current';

scalar largest;

loop(i,

   largest = smax(rem,best(rem,'r'));

   cur(rem) = best(rem,'r')=largest;

   x.l(i) = best(cur,'x');

   y.l(i) = best(cur,'y');

   r.l(i) = best(cur,'r');

   rem(cur) = no;

);

z.l = zbest;

 

* reset to default for next solves

circleswo.solprint = %solprint.On%;

 

$endIf

 

 

*-------------------------------------------------------------------

* Global NLP solver

* with or without symmetry breaker

*-------------------------------------------------------------------

 

$ifThen %Global% == 1

 

option qcp=baron, reslim=3600;

option threads=-1;

solve circlesw maximizing z using qcp;

 

$endIf

 

*-------------------------------------------------------------------

* Reporting

*-------------------------------------------------------------------

 

display z.l;

 

parameter results(i,*);

results(i,'x') = x.l(i);

results(i,'y') = y.l(i);

results(i,'r') = r.l(i);

display results;

 

 



Notes: 
  • When we find a solution with the multi-start local solver algorithm, we have the \(\color{darkred}r_i\) unsorted. To be able to use this solution as a starting point for the global solver we (assuming it uses the symmetry breaker constraint), we need to sort the solution so it is feasible w.r.t. to the symmetry constraint. 

Viewing all articles
Browse latest Browse all 804

Trending Articles