0% found this document useful (0 votes)
64 views

MCC Esa99 Final

The document describes an algorithm for computing the smallest enclosing ball (SEB) of a point set in d-dimensional space. The algorithm uses a pivoting approach similar to the simplex method for linear programming. It maintains intermediate solutions robustly by updating previous information instead of recomputing from scratch. The algorithm is implemented in a 300 line C++ program that is fast for dimensions up to 20, robust, and simple to implement.

Uploaded by

Ademar Cardoso
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
64 views

MCC Esa99 Final

The document describes an algorithm for computing the smallest enclosing ball (SEB) of a point set in d-dimensional space. The algorithm uses a pivoting approach similar to the simplex method for linear programming. It maintains intermediate solutions robustly by updating previous information instead of recomputing from scratch. The algorithm is implemented in a 300 line C++ program that is fast for dimensions up to 20, robust, and simple to implement.

Uploaded by

Ademar Cardoso
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Fast and Robust Smallest Enclosing Balls

Bernd G artner
Institut f ur Theoretische Informatik, ETH Z urich, ETH-Zentrum, CH-8092 Z urich, Switzerland ( [email protected])

Abstract. I describe a C++ program for computing the smallest enclosing ball of a point set in d-dimensional space, using oating-point arithmetic only. The program is very fast for d 20, robust and simple (about 300 lines of code, excluding prototype denitions). Its new features are a pivoting approach resembling the simplex method for linear programming, and a robust update scheme for intermediate solutions. The program with complete documentation following the literate programming paradigm [3] is available on the Web.1

Introduction

The smallest enclosing ball (or Euclidean 1-center) problem is a classical problem of computational geometry. It has a long history which dates back to 1857 when Sylvester formulated it for points in the plane [8]. The rst optimal linear-time algorithm for xed dimension was given by Megiddo in 1982 [4]. In 1991, Emo Welzl developed a simple randomized method to solve the problem in expected linear time [9]. In contrast to Megiddos method, his algorithm is easy to implement and very fast in practice, for dimensions 2 and 3. In higher dimensions, a heuristic move-to-front variant considerably improves the performance. The roots of the program I will describe go back to 1991 when I rst implemented Emo Welzls new method. Using the move-to-front variant I was able to solve problems on 5000 points up to dimension d = 10 (see [9] for all results). Back then, the program was written in MODULA-2 (the language I had learned in my undergraduate CS courses), and it was running on a 80386 PC with 20 MHz. After the algorithm and the implementation results had been published, we constantly received requests for source code, from an amazingly wide range of application areas. To name some, there was environmental science (design and optimization of solvents), pattern recognition (nding reference points), biology (proteine analysis), political science (analysis of party spectra), mechanical engineering (stress optimization) and computer graphics (ray tracing, culling). Soon it became clear that the MODULA-2 source was not of great help in serving these requests; people wanted C or C++ code. Independently, at least two
This work was supported by grants from the Swiss Federal Oce for Education and Science (Projects ESPRIT IV LTR No. 21957 CGAL and No. 28155 GALIA). http://www.inf.ethz.ch/personal/gaertner/miniball.html

persons ported the undocumented program to C. (One of them remarked that although we dont understand the complete procedure, we are condent that the algorithm is perfect.) Vishwa Ranjan kindly made his carefully adapted C program accessible to me; subsequently, I was able to distribute a C version. (An independent implementation by David Eberly for the cases d = 2, 3 based on [9] is available online. 2 ) Another shortcoming of my programpersisting in the C codewas the lack of numerical stability, an issue not yet fashionable in computational geometry at that time. The main primitive of the code was to solve a linear system, and this was done with plain Gaussian elimination, with no special provisions to deal with ill-conditioned systems. In my defense I must say that the code was originally only made to get test results for Emos paper, and in the tests with the usual random point sets I did for that, I discovered no problems, of course. Others did. David White, who was developing code for the more general problem of nding the smallest ball enclosing balls, noticed unstable behavior of my program, especially in higher dimensions. In his code, he replaced the naive Gaussian elimination approach by a solution method based on singular value decomposition (SVD). This made his program pretty robust, and a C++ version (excluding the SVD routines which are taken from Numerical Recipes in C [6]) is available from David Whites Web page. 3 Meanwhile, I got involved in the CGAL project, a joint eort of seven European sites to build a C++ library of computational geometry algorithms. 4 To prepare my code for the library, I nally wrote a C++ version of it from scratch. As the main improvement, the code was no longer solving a complete linear system in every step, but was updating previous imformation instead. A CGALized version of this code is now contained in the library, and using it together with any exact (multiple precision) number type results in error-free computations. Still, the numerical problems arising in oating-point computations were not solved. Stefan Gottschalk, one of the rst users of my new C++ code, encountered singularities in the update routines, in particular if input points are (almost) cospherical, very close together or even equal. The eect is that center and squared radius of the ball maintained by the algorithm can become very large or even undened due to exponent overow, even though the smallest enclosing ball problem itself is well-behaved in the sense that small perturbations of the input points have only a small inuence on the result. As it turned out, previous implementations suered from an inappropriate representation of intermediate balls that ignores the good-naturedness of the problem. The new representation scheme respects the underlying geometryit actually resulted from a deeper understanding of the geometric situation and solves most of the problems. The second ingredient is a new high-level algorithm replacing the move-tofront method. Its goal is to decrease the overall number of intermediate solutions
2 3 4

http://www.cs.unc.edu/~eberly/ http://vision.ucsd.edu/~dwhite http://www.cs.uu.nl/CGAL

computed during the algorithm. This is achieved by reducing the problem to a small number of calls to the move-to-front method, with only a small point set in each call. These calls can then be interpreted as pivot steps of the method. The advantages are a substantial improvement in runtime for dimensions d 10, and much more robust behavior. The result is a program which I think reaches a high level of eciency and stability per lines of code. In simplicity, it is almost comparable to the popular approximation algorithms from the Graphics Gems collection [7, 10]; because the latter usually compute suboptimal balls, the authors stress their simplicity as the main feature. The code presented here shares this feature, while computing the optimal ball.

The Algorithms

Given an n-point set P = {p1 , . . . , pn } Rd , let mb(P ) denote the ball of smallest radius that contains P . mb(P ) exists and is unique. For P, B R d , P B = , let mb(P, B ) be the smallest ball that contains P and has all points of B on its boundary. We have mb(P ) = mb(P, ), and if mb(P, B ) exists, it is unique. Finally, dene mb(B ) := mb(, B ) to be the smallest ball with all points of B on the boundary (if it exists). A support set of (P, B ) is an inclusion-minimal subset of P with mb(P, B ) = mb(S, B ). If the points in B are anely independent, there always exists a support set of size at most d + 1 |B |, and we have mb(S, B ) = mb(S B ). If p mb(P, B ), then p lies on the boundary of mb(P {p}, B ), provided the latter existsthat means, mb(P {p}, B ) = mb(P, B {p}). All this is well-known, see e.g. [9] and the references there. The basis of our method is Emo Welzls move-to-front heuristic to compute mb(P, B ) if it exists[9]. The method keeps the points in an ordered list L which gets reorganized as the algorithm runs. Let Li denote the length-i prex of the list, pi the element at position i in L. Initially, L = Ln stores the points of P in random order. Algorithm 1. mtf mb(Ln , B ): (* returns mb(Ln , B ) *) mb := mb(B ) IF |B | = d + 1 THEN RETURN mb END FOR i = 1 TO n DO IF pi mb THEN mb := mtf mb(Li1 , B {pi }) update L by moving pi to the front END END RETURN mb

This algorithm computes mb(P, B ) incrementally, by adding one point after another from the list. One can prove that during the call to mtf mb(Ln , ), all sets B that come up in recursive calls are anely independent. Together with the above mentioned facts, this ensures the correctness of the method. By induction, one can also show that upon termination, a support set of (P, B ) appears as a prex Ls of the list L, and below we will assume that the algorithm returns the size s along with mb. The practical eciency comes from the fact that important points (which for the purpose of the method are points outside the current ball) are moved to the front and will therefore be processed early in subsequent recursive calls. The eect is that the ball maintained by the algorithm gets large fast. The second algorithm uses the move-to-front variant only as a subroutine for small point sets. Large-scale problems are handled by a pivoting variant which in every iteration adds the point which is most promising in the sense that it has largest distance from the current ball. Under this scheme, the ball gets large even faster, and the method usually terminates after very few iterations. (As the test results in Section 5 show, the move-to-front variant will still be faster for d not too large, but there are good reasons to prefer the pivoting variant in any case.) Let e(p, mb) denote the excess of p w.r.t. mb, dened as p c 2 r2 , c and 2 r the center and squared radius of mb. Algorithm 2. pivot mb(Ln ): (* returns mb(Ln ) *) t := 1 (mb, s) := mtf mb(Lt , ) REPEAT (* Invariant: mb = mb(Lt ) = mb(Ls ), s t *) choose k > t with e := e(pk , mb) maximal IF e > 0 THEN (mb, s ) := mtf mb(Ls , {pk }) update L by moving pk to the front t := s + 1 s := s + 1 END UNTIL e 0 RETURN mb Because mb gets larger in every iteration, the procedure eventually terminates. The computation of (mb, s ) can be viewed as a pivot step of the method, involving at most d + 2 points. The choice of k is done according to a heuristic pivot rule, with the intention of keeping the overall number of pivot steps small. With this interpretation, the procedure pivot mb is similar in spirit to the simplex method for linear programming [1], and it has in fact been designed with regard to the simplex methods eciency in practice.

The Primitive Operation

During a call to algorithm pivot mb, all nontrivial computations take place in the primitive operation of computing mb(B ) for a given set B in the subcalls to mtf mb. The algorithm guarantees that B is always a set of anely independent points, from which |B | d + 1 follows. In that case, mb(B ) is determined by the unique circumsphere of the points in B with center restricted to the ane hull of B . This means, the center c and squared radius r 2 satisfy the following system of equations, where B = {q0 , . . . , qm1 }, m d + 1. (qi c)T (qi c) = r 2 ,
m1 i=0 m1

i = 0, . . . m 1,

i qi = c, i = 1.
i=0

Dening Qi := qi q0 , for i = 0, . . . , m 1 and C := c q0 , the system can be rewritten as C T C = r2 , (Qi C )T (Qi C ) = r 2 ,


m1 i=1

i = 1, . . . , m 1,

(1)

i Qi = C. Substituting C with i=1 i Qi in the equations (1), we deduce a linear system in the variables 1 , . . . , m1 which we can write as QT 1 1 Q1 . . . (2) AB . , . . = m1 QT m1 Qm1 where T 2QT 1 Q1 2Q1 Qm1 . . . . AB := . . . T Q 2 Q Q 2QT m1 m1 1 m1
m1

(3)

Computing the values of 1 , . . . , m1 amounts to solving the linear system (2). C and r 2 are then easily obtained via
m1

C=
i=1

i Qi ,

r2 = C T C.

(4)

We refer to C as the relative center w.r.t. the (ordered) set B .

The Implementation

Algorithms 1 and 2 are implemented in a straightforward manner, following the pseudocode given above. In case of algorithm mtf mb, the set B does not appear as a formal parameter but is updated before and after the recursive call by pushing resp. popping the point pi . This stack-like behavior of B also makes it possible to implement the primitive operation in a simple, robust and ecient way. More precisely, the algorithm maintains a device for solving system (2) which can conveniently be updated if B changes. The update is easy when element pi is removed from B we just need to remember the status prior to the addition of pi . In the course of this addition, however, some real work is necessary. 1 A possible device for solving system (2) is the explicit inverse A B of the matrix AB dened in (3), along with the vector QT 1 Q1 . . vB := . . QT m1 Qm1 Having this inverse available, it takes just a matrix-vector multiplication to obtain the values 1 , . . . , m1 that dene C via (4). Assume B is enlarged by pushing another point qm . Dene B = B {qm }. 1 1 Lets analyze how A B can be obtained from AB . We have 2QT 1 Qm . . AB . AB = , T 2Qm1 Qm T T 2QT 1 Qm 2Qm1 Qm 2Qm Qm and it is not hard to check that this equation can be written as 0 . . A B = L A B . LT , 0 0 0 z where L= and 1 .. . 1 1 m1 0 . . . , 0 1 1 2QT 1 Qm . . 1 . := . . = AB . m1 2QT Q m1 m

(5)

2QT 1 Qm . 1 T T . z = 2QT . m Qm (2Q1 Qm , , 2Qm1 Qm )AB . T 2Qm1 Qm

(6)

This implies
1 A B

0 . 1 . . = (LT )1 AB L1 , 0 0 0 1/z 1 .. . 1 1 m1 0 . . . . 0 1

(7)

where

L1 =

Expanding (7) then gives the desired update formula


1 A B = 1 T A B + /z /z T /z 1/z

(8)

with and z as dened in (5) and (6). Equation (8) shows that AB may become ill-conditioned (and the entries 1 of A B very large and unreliable), if z evaluates to a very small number. The subsequent lemma develops a geometric interpretation of z from which we can see that this happens exactly if the new point qm is very close to the ane hull of the previous ones. This can be the case e.g. if input points are very close together or even equal. To deal with such problems, we need a device that stays bounded in every update operation. As it turns out, a suitable device is the (d d)-matrix
1 T MB := 2QB A B QB ,

where QB := (Q1 Qm1 ) stores the points Qi as columns. Lemma 1 below proves that the entries of MB stay bounded, no matter what. We will also see how the new center is obtained from MB , which is not clear anymore now. Lemma 1. (i) With as in (5), we have
m1

m, i Qi = Q
i=1

m is the projection of Qm onto the subspace spanned by the Qi . where Q m. (ii) MB Qm = Q m )T (Qm Q m ), i.e. z is twice the distance from Qm to its (iii) z = 2(Qm Q projection.

(iv) If C and r 2 are relative center and squared radius w.r.t. B , then the new relative center C and squared radius r 2 (w.r.t. B ) satisfy e m ), C = C + (Qm Q z e2 r 2 = r2 + , 2z where e = (Qm C )T (Qm C ) r 2 . (v) MB is updated according to 2 m )(Qm Q m )T . MB = MB + (Qm Q z (11) (9) (10)

The proof involves only elementary calculations and is omitted here. Property (ii) gives MB an interpretation as a linear function: MB is the projection onto the linear subspace spanned by Q1 , . . . , Qm1 . Furthermore, property (v) implies that MB stays bounded. This of course does not mean that no bad errors can m can get hugely amplied if z is occur anymore. In (11), small errors in Qm Q close to zero. Still, MB degrades gracefully in this case, and the typical relative error in the nal ball is by an order of magnitude smaller if the device MB is 1 used instead of A B . The lemma naturally suggests an algorithm to obtain C , r 2 and MB from m , e and z . C, r2 and MB , using the values Q As already mentioned, even MB may get inaccurate, in consequence of a very small value of z before. The strategy to deal with this is very simple: we ignore push operations leading to such dangerously small values! In the ambient algorithm mtf mb this means that the point to be pushed is treated as if it were inside the current ball (in pivot mb the push operation is never dangerous, because we push onto an empty set B ). Under this scheme, it could happen that points end up outside the nal ball computed by mtf mb, but they will not be very far outside, if we choose the threshold for z appropriately. The criterion is that we ignore a push operation if and only if the relative size of z is small, meaning that z < 2 rcurr (12)

2 for some constant , where rcurr is the current squared radius. Now consider a k subcall to mtf mb(Ls , {p }) inside the algorithm pivot mb, and assume that a point p Ls ends up outside the ball mb0 with support set S0 and radius r0 computed by this subcall. One can check that after the last time the query pi mb ? has been executed with pi being equal to p in mtf mb, no successful push operations have occured anymore. It follows that mb = mb0 in this last query, the query had a positive answer (because p lies outside), and the subsequent push operation failed. This 2 means, we had z/r0 < at that time.

Let rmax denote the radius of mb(Ls , {pk }). Because of (10), we also had 2 at the time of the failing push operation, where e is the excess of e /2z rmax p w.r.t. a ball mb(B {pk }) with B S0 . We then get
2

e
2 rmax

2z 2z 2 2. 2 rmax r0

Assuming that rmax is not much larger than r0 (we expect push operations to fail rather at the end of the computation, when the ball is already large), we can argue that e 2 = O ( ). r0 Moreover, because mb0 contains the intersection of mb(B {pk }) with the ane hull of B {pk }, to which set p is quite close due to z being small, we also get e0 = O( ), 2 r0 (13)

where e0 is the excess of p w.r.t. the nal ball mb0 , as desired. This argument is not a strict proof for the correctness of our rejection criterion, but it explains why the latter works well in practice. In the code, is chosen as 1032 . Because of (13), the relative error of a point w.r.t. the nal ball is then expected to stay below 1016 in magnitude. The latter value is the relative accuracy in the typical situations where the threshold criterion is not applied by the algorithm at all. Thus, is chosen in such a way that even when the criterion comes in, the resulting error does not go up. Checking While it is easy to verify that the computed ball is admissible in the sense that it contains all input points and has all support points on the boundary (approximately), its optimality does not yet follow from this; if there are less than d + 1 support points, many balls are admissible with respect to this denition. The following lemma gives an optimality condition. Lemma 2. Let S be a set of anely independent points. mb(S ) is the smallest enclosing ball of S if and only if its center lies in the convex hull of S . The statement seems to be folklore and can be proved e.g. by using the Karush-Kuhn-Tucker optimality conditions for constrained optimization [5], or by elementary methods. From Section 2 we know that the algorithm should compute a support set S that behaves according to the lemma; still, we would like to have a way to check this in order to safeguard against numerical errors that may lead to admissible 1 balls which are too large. Under the device A B , this is very simplethe coecients i we extract from system (2) in this case give us the desired information: exactly if they are all nonnegative, S denes the optimal ball.

The weakness in this argumentation is that due to (possibly substantial) 1 errors in A B , the i might appear positive, although they are not. One has to be aware that checking in this case only adds more plausibility to a seemingly correct result. Real checking would ultimately require the use of exact arithmetic, which is just not the point of this code. Still, if the plausibility test fails (and some i turn out to be far below zero), we do know that something went wrong, which is important information in evaluating the code. Unfortunately, in using the improved device MB during the computations, we do not have immediate access to the i . To obtain them, we express C as well as the points Q1 , . . . , Qm1 with respect to a dierent basis of the linear span of Q1 , . . . , Qm1 . In this representation, the linear combination of the Qi that denes C will be easy to deduce. i , i = The basis we use will be the set of (pairwise orthogonal) vectors Qi Q 1, . . . , m 1. From the update formula for the center (9) we immediately deduce that
m1 i=1

C=

i ), fi (Qi Q

where fi is the value e/z that was computed according to Lemma 1(iv) when pushing qi . This means, the coordinates of C in the new basis are (f1 , . . . , fm1 ). To get the representations of the Qi , we start o by rewriting MB as
m1

MB =
k=1

2 k )(Qk Q k )T , (Qk Q zk

which follows from Lemma 1(v). Here, zk denotes the value z we got when pushing point qk . k Now consider the point Qi . We need to know the coecient ik of Qk Q in the representation
m1

Qi =
k=1

k ). ik (Qk Q

With MB i :=

k=1

2 k )(Qk Q k )T (Qk Q zk MB i Q i = Q i

(14)

we get (after adding qi to B , Qi projects to itself). Via (14), this entails i,i+1 = = i,m1 = 0 and 2 k )T Qi , k i. ik = (Qk Q zk In particular we get ii = 1. The coecients i in the equation
m1

C=
i=1

i Qi

are now easy to compute in the new representations of C and the Qi we have just developed. For this, we need to solve the linear system f1 1 a11 am1,1 . . . . . . . . . = . . . a1,m1 am1,m1 m1 fm1 This system is triangulareverything below the diagonal is zero, and the entries on the diagonal are 1. So we can get the i by a simple back substitution, according to
m1

i = f i Finally, we set

ki k .
k=i+1

m1

0 = 1

k ,
k=1

and check whether all these values are nonnegative. How much eort is necessary to determine the values ik ? Here comes the punch line: if we actually represent the MB i according to (14) and during the push of qi evaluate the product
i1

MB i1 Qi =
k=1

2 k )(Qk Q k )T Qi = (Qk Q zk

i1 k=1

k) ik (Qk Q

according to this expansion, we have already computed ik by the time we need it for the checking! Moreover, if we make representation (14) implicit by only storing the zk and k , we can even perform the multiplication MB i1 Qi with the vectors Qk Q (di) arithmetic operations, compared to (d2 ) operations when we really keep MB as a matrix or a sum of matrices. The resulting implementation of the push routine is extremely simple and compact (about 50 lines of code), and it allows the checker to be implemented in 10 more lines of code.

Experimental Results

I have tested the algorithm on various point sets: random point sets (to evaluate the speed), vertices of a regular simplex (to determine the dimension limits) and (almost) cospherical points (to check the degeneracy handling). In further rounds, all these examples have been equipped with extra degeneracies obtained by duplicating input points, replacing them by clouds of points very close together, or embedding them into a higher dimensional space. This covers all inputs that have ever been reported as problematic to me. A test suite

(distributed with the code) automatically generates all these scenarios from the master point sets and prints out the results. In most cases, the correct ball is obtained by the pivoting method, while the move-to-front method frequently fails (results range from mildly wrong to wildly wrong on cospherical points, and under input point duplication resp. replacement by clouds). This means, although the move-to-front approach is still slightly faster than pivoting in low dimensions (see the results in the next paragraph), it is highly advisable to use the pivoting approach; it seems to work very well together with the robust update scheme based on the matrix MB , as described in Section 4. The main drawbacks of the move-to-front method are its dependence on the order of the input points, and its higher number of push operations (the more you push, the more can go wrong). Of course, the input order can be randomly rearranged prior to computation (as originally suggested in [9]), but that eats up the gain in runtime over the pivoting method. On the other hand, if one does not rearrange, it is very easy to come up with bad input orders (try a set of points ordered along a line). Random point sets. I have tested the algorithm on random point sets up to dimension 30 to evaluate the speed of the method, in particular with respect to the relation between the pivoting and the move-to-front variant. Table 1 (left) shows the respective runtimes for 100, 000 points randomly chosen in the d-dimensional unit cube, in logarithmic scale (averaged over 100 runs). All runtimes (excluding the time for generating and storing the points) have been obtained on a SUN Ultra-Sparc II (248 MHz), compiling with the GNU C++-Compiler g++ Version 2.8.1, and options -O3 -funroll-loops. The latter option advises the compiler to perform loop unrolling (and g++ does this to quite some extent). This is possible because the dimension is xed at compile time via a template argument. By this mechanism, one also gets rid of dynamic storage management. As it turns out, the move-to-front method is faster than the pivoting approach up to dimension 8 but then loses dramatically. In dimension 20, pivoting is already more than ten times faster. Both methods are exponential in the dimension, but for applications in low dimensions (e.g. d = 3), even 1, 000, 000 points can be handled in about two seconds. Vertices of a simplex. The results for random point sets suggest that dimension 30 is still feasible using the pivoting method. This, however, is not the case for all inputs. In high dimensions, the runtime is basically determined by the calls to the move-to-front method with point set S {pi }, S the current support set. We know that |S | d + 1, but if the input is random, |S | will frequently be smaller (in dimension 20, for example, the average number of support points turns out to be around 17). In this case, a pivot step and therefore the complete algorithm is much faster than in the worst case. To test this worst case, I have chosen as input the vertices of a regular d-simplex in dimension d, spanned by the unit vectors. In this case, the number of support points is d. Table 1 (right) shows the result (move-to-front and pivoting variant behave similarly). Note that to

s 409.6 204.8 102.4 51.2 25.6 12.8 6.4 3.2 1.6 .8 .4 .2 .1 .05 1 5 10 15 20 25 30 d

s 102.4 51.2 25.6 12.8 6.4 3.2 1.6 .8 .4 .2 .1 .05 10 15 20 d

Table 1. Runtime in seconds for 100, 000 random points in dimension d: pivoting (solid line) and move-to-front (dotted line) (left). Runtime in seconds on regular d-simplex in dimension d (right).

solve the problem on 20 points in dimension 20, one needs about as long as for 100, 000 random points in dimension 26! As a conclusion, the method reaches its limits much earlier than in dimension 30, when it comes to the worst case. In dimension 20, however, you can still expect reasonable performance in any case. Cospherical points. Here, the master point sets are exactly cocircular points in dimension 2, almost cospherical points in higher dimensions (obtained by scaling random vectors to unit length), a tesselation of the unit sphere in 3-space by longitude/latitude values, and vertices of a regular d-cube. While the pivoting method routinely handles most test scenarios, the move-to-front method mainly has problems with duplicated input points and slightly perturbed inputs. It may take very long and computes mildly wrong results in most cases. The slow behavior is induced by many failing push-operations due to the value z being too small, see Section 4. This causes many points which have mistakenly been treated as inside the current ball to reappear outside later. The most dicult problems for the pivoting method arise from the set of 6144 integer points on the circle around the origin with squared radius r 2 = 3728702916375125. The set itself is handled without any rounding errors at all appearing in the result (this is only possible because r 2 still ts into a oatingpoint value of the C++ type double). However, embedding this point set into 4-space (by adding zeros in the third and fourth coordinate), combined with a random perturbation by a relative amount of about 1030 in each coordinate makes the algorithm fail occasionally. In these case, the computed support set does not have the orgin in its convex hull, which is detected by the checking routine.

Conclusion

I have presented a simple, fast and robust code to compute smallest enclosing balls. The program is the last step so far in a chain of improvements and simpli-

cations of the original program written back in 1991. The distinguishing feature is the nice interplay between a new high-level algorithm (the pivoting method) and improved low-level primitives (the MB -based update scheme). For dimensions d 10, the method is extremely fast, beyond that it slows down a bit, and for d > 20 it is not suitable anymore in some cases. This is because every pivot step (a call to the move-to-front method with few points) takes time exponential in d. Even slight improvements here would considerably boost the performance of the whole algorithm. At this point, it is important to note that high dimension is not prohibitive for the smallest enclosing ball problem itself, only for the method presented. Interior point methods, or real simplex-type methods in the sense that the pivot step is a polynomial-time operation (see e.g.[2]) might be able to handle very high dimensions in practice, but most likely at the cost of losing the simplicity and stability of the solution I gave here.

Acknowledgment
I would like to thank all the people that have in one way or the other contributed to this code over the last eight years, by using previous versions, making suggestions and reporting bugs. Special thanks go to Emo Welzl for acquainting me with his algorithm eight years ago, and for always keeping an eye on the progress.

References
1. V. Chv atal. Linear Programming. W. H. Freeman, New York, NY, 1983. 2. B. G artner. Geometric optimization. Lecture Notes for the Equinoctial School on Geometric Computing, ETH Z urich, 1997, http://www.inf.ethz.ch/personal/ gaertner/publications.html 3. Donald E. Knuth. Literate programming. The Computer Journal, 27(2):97111, 1984. 4. N. Megiddo. Linear-time algorithms for linear programming in R 3 and related problems. In Proc. 23rd Annu. IEEE Sympos. Found. Comput. Sci., pages 329 338, 1982. 5. A. L. Peressini, F. E. Sullivan, and J. J. Uhl. The Mathematics of Nonlinear Programming. Undergraduate Texts in Mathematics. Springer-Verlag, 1988. 6. William H. Press, Brian P. Flannery, Saul A. Teukolsky, and William T. Vetterling. Numerical Recipes in C. Cambridge University Press, Cambridge, England, 2nd edition, 1993. 7. J. Ritter. An ecient bounding sphere. In Andrew S. Glassner, editor, Graphics Gems. Academic Press, Boston, MA, 1990. 8. J. J. Sylvester. A question on the geometry of situation. Quart. J. Math., 1:79, 1857. 9. Emo Welzl. Smallest enclosing disks (balls and ellipsoids). In H. Maurer, editor, New Results and New Trends in Computer Science, volume 555 of Lecture Notes Comput. Sci., pages 359370. Springer-Verlag, 1991. 10. X. Wu. A linear-time simple bounding volume algorithm. In D. Kirk, editor, Graphics Gems III. Academic Press, Boston, MA, 1992.

You might also like