The fact that this problem can be solved using "direct search" (as can be seen in another answer ) means that we can consider this as a global optimization . There are various ways to solve such problems, each of which is suitable for certain scenarios. Out of my personal curiosity, I decided to solve this problem using a genetic algorithm .
Generally speaking, such an algorithm requires that we consider a solution as a set of “genes” prone to “evolution” with a certain “fitness function”. As it happens, it's pretty easy to identify the genes and fitness function in this problem:
- Genes:
x , y , r . - Fitness function: technically the maximum lap area, but this is equivalent to the maximum
r (or minimum -r , since the algorithm requires minimizing the function). - A particular limitation is that if
r greater than the Euclidean distance to the nearest of the provided points (that is, the circle contains a point), the body "dies."
The basic implementation of such an algorithm is given below (“basic” because it is completely non-optimized, and there are many possibilities for no pun optimization in this task).
function [x,y,r] = q42806059b(cloudOfPoints) % Problem setup if nargin == 0 rng(1) cloudOfPoints = rand(100,2)*5; % equivalent to Ander initialization. end %{ figure(); plot(cloudOfPoints(:,1),cloudOfPoints(:,2),'.w'); hold on; axis square; set(gca,'Color','k'); plot(0.7832,2.0694,'ro'); plot(0.7832,2.0694,'r*'); %} nVariables = 3; options = optimoptions(@ga,'UseVectorized',true,'CreationFcn',@gacreationuniform,... 'PopulationSize',1000); S = max(cloudOfPoints,[],1); L = min(cloudOfPoints,[],1); % Find geometric bounds: % In R2017a: use [S,L] = bounds(cloudOfPoints,1); % Here we also define distance-from-boundary constraints. g = ga(@(g)vectorized_fitness(g,cloudOfPoints,[L;S]), nVariables,... [],[], [],[], [L 0],[S min(SL)], [], options); x = g(1); y = g(2); r = g(3); %{ plot(x,y,'ro'); plot(x,y,'r*'); rectangle('Position',[xr,yr,2*r,2*r],'Curvature',[1 1],'EdgeColor','r'); %} function f = vectorized_fitness(genes,pts,extent) % genes = [x,y,r] % extent = [Xmin Ymin; Xmax Ymax] % f, the fitness, is the largest radius. f = min(pdist2(genes(:,1:2), pts, 'euclidean'), [], 2); % Instant death if circle contains a point: f( f < genes(:,3) ) = Inf; % Instant death if circle is too close to boundary: f( any( genes(:,3) > genes(:,1:2) - extent(1,:) | ... genes(:,3) > extent(2,:) - genes(:,1:2), 2) ) = Inf; % Note: this condition may possibly be specified using the A,b inputs of ga(). f(isfinite(f)) = -genes(isfinite(f),3); %DEBUG: %{ scatter(genes(:,1),genes(:,2),10 ,[0, .447, .741] ,'o'); % All z = ~isfinite(f); scatter(genes(z,1),genes(z,2),30,'r','x'); % Killed z = isfinite(f); scatter(genes(z,1),genes(z,2),30,'g','h'); % Surviving [~,I] = sort(f); scatter(genes(I(1:5),1),genes(I(1:5),2),30,'y','p'); % Elite %}
And here is a graph of the “temporary passage” of 47 generations of a typical launch:

(Where the blue dots are the current generation, the red crosses are “killed by insta” organisms, the green hexagrams are “non-insta-killed” organisms, and the red circle indicates the destination).