NMinimize: community-sourced examples to extend documentation​
​by W. Craig Carter
The documentation for the Wolfram Language and the FrontEnd are great--and the working examples provide useful starting points.
​
Every once in a while, I find a case where it is difficult to figure out how to do something and can’t find a working example. After struggling a bit, I might get something working.
​
That working example might be useful for someone else. I show here a few additional minimal working examples for NMinimize.
​
I’d like to encourage others who find--what they consider to be--good working examples, and then post them to the community. Something like a crowd-sourced appendix to the documentation.
​
I wonder if it might be possible version of “ResourceAdditionalDocumentation” constructed in a parallel fashion to ResourceData or ResourceFunction.

Extended examples from the documentation

I recently ran into one where I was trying to minimize a function of a set of 2d points. It took me a while to get things to work, but I thought I would share here for anyone who is trying to do something similar.

Geometry Problem (4)

This is an example from the documentation for NMinimize: Example from the documentation
​
Find the minimum distance between two disks of radius 1 centered at
c
1
={0,0}
and
c
2
={2,1}
. Let
p
1
be a point on disk 1. Let
p
2
be a point on disk 2. The objective is to minimize
||
p
1
-
p
2
||
subject to constraints
||
p
1
||≤1,||
p
2
-
c
2
||≤1
:
This finds the two points, p1 and p2, that are closest. p1 and p2 are in separate fixed disks.
In[]:=
res=NMinimize[{Norm[p1-p2],c2=={2,1},Norm[p1]≤1,Norm[p2-c2]≤1},{p1∈Vectors[2,Reals],p2∈Vectors[2,Reals]}]
Out[]=
{0.236069,{p1{0.894427,0.447213},p2{1.10557,0.552787}}}
visualize:
In[]:=
Graphics[{{Lighter[Blue],Disk[]},{Lighter[Red],Disk[{2,1}]},{Green,PointSize[0.03],Point[{p1,p2}/.res〚2〛]}},Axes->True]
Out[]=
-1
1
2
3
-1.0
-0.5
0.5
1.0
1.5
2.0
Let’s add a new constraint that p1 must lie along a line with a fixed angle.
NMinimize couldn’t generate initial points without help, nevertheless a plausible solution is obtained
In[]:=
res=NMinimize[{Norm[p1-p2],c2=={2,1},Norm[p1]≤1,Norm[p2-c2]≤1,Element[p1,InfiniteLine[AngleVector[Pi/3],-AngleVector[Pi/3]]]},{p1∈Vectors[2,Reals],p2∈Vectors[2,Reals]}​​]
NMinimize
:NMinimize was unable to generate any initial points satisfying the inequality constraints -1+1.1547Abs[
p1
2
]≤0,-1+
2
Abs[Plus[2]]
+
2
Abs[Plus[2]]
≤0. The initial region specified may not contain any feasible points. Changing the initial region or specifying explicit initial points may provide a better solution.
Out[]=
{0.505971,{p1{0.5,0.866025},p2{1.00396,0.911038}}}
In[]:=
Graphics[{{Lighter[Blue],Disk[]},{Lighter[Red],Disk[{2,1}]},{Green,PointSize[0.03],Point[{p1,p2}/.res〚2〛],​​{Black,​​InfiniteLine[AngleVector[Pi/3],-AngleVector[Pi/3]]}}​​},Axes->True]
Out[]=
To eliminate NMinimize’s warning, one can use a Method that take InitialPoints. NelderMead is one such Method
The syntax for adding initial points isn’t obvious. The following will generate an error
In[]:=
res=NMinimize[{Norm[p1-p2],c2=={2,1},Norm[p1]≤1,Norm[p2-c2]≤1,Element[p1,InfiniteLine[AngleVector[Pi/3],-AngleVector[Pi/3]]]},{p1∈Vectors[2,Reals],p2∈Vectors[2,Reals]},​​Method{"NelderMead","InitialPoints"->{AngleVector[Pi/3],RandomPoint[Disk[{2,1},1]]}}​​​​]
NMinimize
:Inappropriate parameter: InitialPoints -> 
1
2
,
3
2
,{1.84877,0.136573}​, changed to Automatic.
NMinimize
:NMinimize was unable to generate any initial points satisfying the inequality constraints -1+1.1547Abs[
p1
2
]≤0,-1+
2
Abs[Plus[2]]
+
2
Abs[Plus[2]]
≤0. The initial region specified may not contain any feasible points. Changing the initial region or specifying explicit initial points may provide a better solution.
Out[]=
{0.505971,{p1{0.5,0.866025},p2{1.00396,0.911038}}}
In[]:=
Graphics[{{Lighter[Blue],Disk[]},{Lighter[Red],Disk[{2,1}]},{Green,PointSize[0.03],Point[{p1,p2}/.res〚2〛],​​{Black,​​InfiniteLine[AngleVector[Pi/3],-AngleVector[Pi/3]]}}​​},Axes->True]
Out[]=
The Initial points must be a list of flat lists and ordered in the same way the variables are ordered.
In[]:=
res=NMinimize[{Norm[p1-p2],c2=={3,1},Norm[p1]≤1,Norm[p2-c2]≤1,Element[p1,InfiniteLine[AngleVector[Pi/3],-AngleVector[Pi/3]]]},{p1∈Vectors[2,Reals],p2∈Vectors[2,Reals]},​​Method{"NelderMead",​​"InitialPoints"->{Flatten[{AngleVector[Pi/3],-AngleVector[Pi/3]}]}​​}​​​​]
Out[]=
{1.50359,{p1{0.5,0.866025},p2{2.00143,0.946506}}}
In[]:=
Graphics[{{Lighter[Blue],Disk[]},{Lighter[Red],Disk[{3,1}]},{Green,PointSize[0.03],Point[{p1,p2}/.res〚2〛],​​{Black,​​InfiniteLine[AngleVector[Pi/3],-AngleVector[Pi/3]]}}​​},Axes->True]
Out[]=
Let’s suppose we want to add a degree of freedom to the second disk. Fixing the center of the second disk and not using it as a constraint doesn’t work.
In[]:=
Block[{angle=5Pi/12,res,center2={3,1}},​​res=NMinimize[{Norm[p1-p2],Norm[p1]≤1,Norm[p2-center2]≤1,Element[p1,InfiniteLine[AngleVector[angle],-AngleVector[angle]]]},{p1∈Vectors[2,Reals],p2∈Vectors[2,Reals]},​​Method{"NelderMead","InitialPoints"->​​{​​Flatten[{AngleVector[angle],RandomPoint[Disk[center2,1]]}]​​}​​}];​​​​Graphics[{{Lighter[Blue],Disk[]},{Lighter[Red],Disk[{2,1}]},{Green,PointSize[0.03],Point[{p1,p2}/.res〚2〛],​​{Black,​​InfiniteLine[AngleVector[angle],RandomPoint[Disk[center2,1]]]}}​​},Axes->True]​​​​]​​
NMinimize
:Obtained solution does not satisfy the following constraints within Tolerance -> 0.001: -1+
2
Abs[Plus[2]]
+
2
Abs[Plus[2]]
≤0,-1+
2
Abs[Plus[2]]
+
2
Abs[Plus[2]]
≤0.
Out[]=
It can be fixed by using a local variable. Also, note the syntax for adding multiple initial guesses
In[]:=
Block[{angle=5Pi/12,res,fixedCenter={3,2}},​​res=Echo@NMinimize[{Norm[p1-p2],center2==fixedCenter,Norm[p1]≤1,Norm[p2-center2]≤1,Element[p1,InfiniteLine[AngleVector[angle],-AngleVector[angle]]]},{p1∈Vectors[2,Reals],p2∈Vectors[2,Reals]},​​Method{"NelderMead","InitialPoints"->​​{​​Flatten[{AngleVector[angle],RandomPoint[Disk[fixedCenter,1]]}]​​,Flatten[{AngleVector[angle],RandomPoint[Disk[fixedCenter,1]]}]​​}​​}];​​​​Graphics[{{Lighter[Blue],Disk[]},{Lighter[Red],Disk[fixedCenter]},{Green,PointSize[0.03],Point[{p1,p2}/.res〚2〛],​​{Black,​​InfiniteLine[AngleVector[angle],-AngleVector[angle]]}}​​},Axes->True]​​​​]
»
{1.92974,{p1{0.258819,0.965926},p2{2.06436,1.64704}}}
Out[]=
Suppose we want to have the center of the second circle have a degree of freedom as well. The center can be specified as a variable with a vector quantity, but an initial constraint is added for that degree of freedom.
In[]:=
Block[{angle=2Pi/8,res},​​res=Echo@NMinimize[{Norm[p1-p2],Norm[p1]≤1,Norm[p2-center2]≤1,Element[p1,InfiniteLine[AngleVector[angle],-AngleVector[angle]]],​​Element[center2,InfiniteLine[{3,0},{0,1}]]​​},{p1∈Vectors[2,Reals],p2∈Vectors[2,Reals],center2∈Vectors[2,Reals]},​​Method{"NelderMead","InitialPoints"->​​{​​Flatten[{AngleVector[angle],RandomPoint[Disk[{3,0},20]],{RandomReal[{-1,1}],3}}]​​(*,Flatten[{AngleVector[angle],RandomPoint[Disk[center2,1]]}]*)​​}​​}];​​​​Graphics[{{Lighter[Blue],Disk[]},​​{Lighter[Red],Disk[center2]/.res〚2〛},{Green,PointSize[0.03],Point[{p1,p2}/.res〚2〛],​​{Black,​​InfiniteLine[AngleVector[angle],-AngleVector[angle]],​​Darker@Green,​​InfiniteLine[{3,0},{0,1}]​​}}​​},Axes->True]​​​​]
»
{1.29289,{p1{0.707107,0.707107},p2{2.,0.707107},center2{3.,0.707107}}}
Out[]=
Add another degree of freedom by allowing minimization of the angle of the black line (on which the solution p1 is constraint. The last variable (the angle) is no longer a vector.
The initial points are arranged to be consistent.
In[]:=
Block[{res},​​res=Echo@NMinimize[​​{​​Norm[p1-p2],Norm[p1]≤1,​​Norm[p2-center2]≤1,Element[p1,InfiniteLine[AngleVector[angle],-AngleVector[angle]]],​​Element[center2,InfiniteLine[{3,0},{0,1}]]​​},{p1∈Vectors[2,Reals],p2∈Vectors[2,Reals],center2∈Vectors[2,Reals],angle∈Reals},​​Method{"NelderMead","InitialPoints"->​​{​​Flatten[​​{​​AngleVector[Pi],​​RandomPoint[Disk[{3,0},1]],​​RandomReal[{-1,1},2],​​Pi​​}​​]​​}​​}​​]​​;​​​​Graphics[{{Lighter[Blue],Disk[]},​​{Lighter[Red],Disk[center2]/.res〚2〛},{Green,PointSize[0.03],Point[{p1,p2}/.res〚2〛],​​{Black,​​InfiniteLine[AngleVector[angle],-AngleVector[angle]]/.res[[2]],​​InfiniteLine[{3,0},{0,1}]​​}}​​},Axes->True]​​​​]
»
{1.,{p1{1.,3.18763×
-7
10
},p2{2.,2.64317×
-7
10
},center2{3.,2.64235×
-7
10
},angle4.39055×
-7
10
}}
Out[]=