Skip to main content
MethodsX logoLink to MethodsX
. 2023 Mar 25;10:102154. doi: 10.1016/j.mex.2023.102154

On univariate optimal partitioning by complete enumeration

Philippe Aubry 1
PMCID: PMC10119953  PMID: 37091960

Graphical abstract

graphic file with name ga1.jpg

Keywords: Set partitions enumeration, Contiguous partitions, Partition optimization, Data structures for set partitions, Nested loops simulation

Method name: Univariate optimal partitioning by iteratively generating contiguous partitions

Abstract

Partitioning a set of elements into a given number of classes to find a globally optimal solution can be challenging due to the combinatorial explosion of the problem size. In the univariate case, where elements can be ordered, the number of partitions is significantly lower than in the multivariate case, and the problem is easier to handle. In this article, we focus on the univariate case and propose using complete enumeration to find a globally optimal solution. Although complete enumeration may also be computationally prohibitive as the number of elements and classes increases, it can be feasible in some situations. For such cases, we propose an algorithm that generates all contiguous partitions for a variable number of classes to be used with any objective function or set of constraints.

  • •

    We compare exact problem sizes and approximate time complexities for multivariate and univariate partitioning.

  • •

    We fill a technical gap in the literature by providing a valuable tool for researchers or engineers who need to exactly solve unusual univariate partitioning problems.

  • •

    We use a convenient data structure for representing partitions of elements into classes and an iterative algorithm that simulates nested loops for any depth level, allowing for efficient generation of all possible contiguous partitions.


Specifications table

Subject Area: Clustering
More specific subject area: Univariate clustering
Method name: Univariate optimal partitioning by iteratively generating contiguous partitions
Name and reference of original method: not applicable
Resource availability: not applicable

Method details

One classical goal in solving a clustering problem is to determine the optimal partitioning of elements into disjoint subsets (clusters or classes) in such a manner that a certain criterion (cost or objective function) is optimized. Usually, the aim is to discover natural clusters in the dataset at hand. In this article, our ambition is far more modest, and we do not take into account the issue of cluster validity in the sense of techniques for finding a partition that best fits the natural one. With a restricted technical perspective, we are only interested in finding a partition that optimizes a criterion of any kind under any set of constraints.

Let the set of all partitions of N elements into H classes (H<N) be denoted as PN,H and the subset of admissible partitions be denoted as SN,H. Without loss of generality, we consider the maximization of a positive objective function J, formally:

J*=J(P*)=arg maxP∈SN,HJ(P)withJ(P)>0 (1)

The algorithmic approaches that can be considered for solving a given partitioning problem essentially depend on (i) the complexity (in computing time) of the problem at hand; (ii) the nature of the objective function J; and (iii) the nature of possible constraints.

One of the main challenges in this class of problems is the combinatorial explosion that occurs when the number of elements and classes increases. As for any combinatorial optimization problem, the approaches that can be used for optimal partitioning are of several kinds and may primarily be classified into exact and approximate methods (see [30, p. 18, Fig. 1.7]). There are several approximate approaches to address partitioning problems, such as problem-specific heuristics or metaheuristics (see, for instance, [13, Ch. 10] or [9]) or approximation algorithms that have a certain performance guarantee (see, for instance, [18]). However, these methods do not guarantee finding a globally optimal solution, and in the best case, only a good (near-optimal) solution is obtained. This may or may not be a problem in practice, depending on the problem at hand. Nevertheless, in what follows, we focus on finding an exact solution.

To address the limitation of approximate methods, complete enumeration can be proposed to find a globally optimal solution. This brute-force approach consists of performing an exhaustive search in the solution space, evaluating the objective function for all admissible partitions into H classes and choosing one of them that corresponds to the global optimum. However, complete enumeration can be computationally prohibitive even for moderate values of N and H. Therefore, there is a need for more efficient exact approaches that can find the global optimum in a practical amount of time. Two main approaches for avoiding the evaluation of all partitions are dynamic-programming [4], [5], [11], [15], [17], [28] and branch-and-bound methods [6, part I]. An impediment to such approaches is that they focus on specific objective functions or problem settings. This limits the applicability of the existing methods and calls for a more general approach to the problem. Optimal partitioning issues may involve constraints or multiple objective functions, which can further complicate the problem. Developing efficient algorithms that can handle these additional complexities is an ongoing research challenge.

In this article, we make no assumptions regarding the nature of the objective function. We relax the problem of optimal partitioning in the sense that we consider the one-dimensional (univariate) case only, where the values of the variable of interest can be ordered. However, in other respects, we somewhat complicate the optimization issue in the sense that any set of constraints can be taken into account to define the admissible partitions for the problem at hand. Hence, in all generality, univariate optimal partitioning is defined here as the problem of dividing a set of ordered elements into a given number of contiguous classes to optimize some objective function under a specified set of constraints.

Focusing on finding a globally optimal solution, we rely on complete enumeration, which is the most straightforward exact method and the most versatile one, as it can handle any type of objective function and set of constraints.

Our article should not be considered an article providing significant advances in the area of operations research since proposing a new approach is not our goal. This purely technical article is merely intended to provide information that can be useful for researchers or engineers who would be confronted with a similar need and help them save time in their own work. This article should also be of some pedagogical interest for a graduate course in computational statistics for the in-depth teaching of stratified sampling since optimal partitioning in a univariate context is a problem that occurs frequently in this context (see, for instance, [3]).

With this in mind, we aim to answer the following questions: (i) In which situations is it possible to obtain a globally optimal partition in a reasonable computing time? (ii) What (simple) algorithm independent of the nature of the objective function and of the set of constraints can be proposed?

Regarding these questions, after providing a compendium of fundamental results, we provide an efficient ready-to-use iterative algorithm for complete enumeration of contiguous partitions, which is easy to read and understand, so that its computer implementation could be easily reproduced by the readers in the programming language of their choice. Univariate optimal partitioning is seldom documented in the literature, which is generally devoted to multivariate situations. The same is true regarding efficient data structures to handle a partition of a set. As a consequence, to the best of our knowledge, the algorithm for univariate optimal partitioning by complete enumeration introduced in this article has not yet been published in the literature.

If we want to rely on complete enumeration, we need first examine what the restriction to the univariate case changes in terms of time complexity with respect to the multidimensional (multivariate) case.

Number of set partitions — multivariate case

The size of PN,H is given by the Stirling number of the second kind (for details, see, for instance, [8]; [10, pp. 32–41]; [7]; [23, Sec. 3.2]), that is, (e.g., [17, Eq. 6]; [12, p. 63]):

|PN,H|=1H!∑k=0H(−1)H−k(Hk)kN (2)

In the general (multivariate) case, Table 1 illustrates the rapid growth of the number of partitions with N and H (combinatorial explosion). As complete enumeration is practically tractable only for reasonable problem sizes (say, currently, several dozen or hundreds of millions of partitions), when we seek a globally optimal solution, the number of partitions shows that the brute-force approach is unrealistic when N and H are not very small (see Table 1). A useful upper bound is (e.g., [19, p. 115]; [12, p. 306, Fig. V.5]):

|PN,H|<HNH! (3)

Table 1.

Number of partitions (|PN,H|) of N=2(1)30 elements (in row) into H=2(1)5 classes (in column) in the general (multivariate) case. For instance, we have |P22,5|=19137821912055 (bold value).

2 3 4 5

2 1
3 3 1
4 7 6 1
5 15 25 10 1
6 31 90 65 15
7 63 301 350 140
8 127 966 1 701 1 050
9 255 3 025 7 770 6 951
10 511 9 330 34 105 42 525
11 1 023 28 501 145 750 246 730
12 2 047 86 526 611 501 1 379 400
13 4 095 261 625 2 532 530 7 508 501
14 8 191 788 970 10 391 745 40 075 035
15 16 383 2 375 101 42 355 950 210 766 920
16 32 767 7 141 686 171 798 901 1 096 190 550
17 65 535 21 457 825 694 337 290 5 652 751 651
18 131 071 64 439 010 2 798 806 985 28 958 095 545
19 262 143 193 448 101 11 259 666 950 147 589 284 710
20 524 287 580 606 446 45 232 115 901 749 206 090 500
21 1 048 575 1 742 343 625 181 509 070 050 3 791 262 568 401
22 2 097 151 5 228 079 450 727 778 623 825 19 137 821 912 055
23 4 194 303 15 686 335 501 2 916 342 574 750 96 416 888 184 100
24 8 388 607 47 063 200 806 11 681 056 634 501 485 000 783 495 250
25 16 777 215 141 197 991 025 46 771 289 738 810 2 436 684 974 110 750
26 33 554 431 423 610 750 290 187 226 356 946 265 12 230 196 160 292 600
27 67 108 863 1 270 865 805 301 749 329 038 535 350 61 338 207 158 409 100
28 134 217 727 3 812 664 524 766 2 998 587 019 946 700 307 440 364 830 581 000
29 268 435 455 11 438 127 792 025 11 998 160 744 311 600 1 540 200 411 172 850 000
30 536 870 911 34 314 651 811 530 48 004 081 105 038 300 7 713 000 216 608 570 000

Hence, the time complexity for complete enumeration would be approximately O(HN/H!) for the general (multivariate) case. For computer generation of all partitions, the reader is referred to [27, pp. 108–113]; [29, pp. 18–22, 164–166]; [23, Sec. 3.2.1]; [26, Sec. 1.5]; [1, Ch. 17]; [21, pp. 415–418]; [24, Ch. 9], and references therein Tables 1.

Number of contiguous partitions — univariate case

Let a sequence L=(L1<L2<⋯<LL) of L distinct values taken by a variable of interest x. Let PL,H be the set of contiguous partitions of L into H<L classes. A contiguous partition may be defined as a partition such that if La and Lb (La<Lb) are members of the same class, then all intermediate Li (La<Li<Lb) are also members of this class.

The purpose of this section is to examine how many contiguous partitions exist — depending on the values taken by L and H — and to compare with the general case.

Imagine L distinct values lying on a line according to their order. A contiguous partition of the L values into H classes may be represented by H−1 dividing points within any of the L−1 intervals between the adjacent values. Hence, the number of contiguous partitions is equal to the number of ways of choosing the H−1 dividing points among the L−1 intervals, that is:

|PL,H|=(L−1H−1) (4)

It is also possible to follow an enumerative approach (even if we have to recognize that this is much more cumbersome). We write the number of partitions of L into H<L contiguous classes by enumerating all solutions and counting them, which allows us to write the following sequence of H−1 summations:

|PL,H|=∑i1=1L−(H−1)∑i2=i1+1L−(H−2)∑i3=i2+1L−(H−3)⋯∑ih=ih−1+1L−(H−h)⋯∑iH−1=iH−2+1L−11 (5)

According to the Appendix, as expected, the closed-form equivalent to expression (5) is:

|PL,H|=∏h=1H−11h(L−h)=(L−1H−1) (6)

In the univariate case, Table 2 illustrates the growth of the problem size according to L and H. The number of contiguous partitions shows that the brute-force approach is more practical than in the general case (compare, for instance, the number of partitions for 22 elements and 5 classes, in bold values in Tables 1 and 2). A possible upper bound is:

|PL,H|≤(L−1)(H−1)(H−1)! (7)

Table 2.

Number of contiguous partitions (|PL,H|) of L=2(1)30 distinct values (in row) into H=2(1)10 classes (in column). For instance, we have |P22,5|=5985 (bold value).

2 3 4 5 6 7 8 9 10
2 1
3 2 1
4 3 3 1
5 4 6 4 1
6 5 10 10 5 1
7 6 15 20 15 6 1
8 7 21 35 35 21 7 1
9 8 28 56 70 56 28 8 1
10 9 36 84 126 126 84 36 9 1
11 10 45 120 210 252 210 120 45 10
12 11 55 165 330 462 462 330 165 55
13 12 66 220 495 792 924 792 495 220
14 13 78 286 715 1 287 1 716 1 716 1 287 715
15 14 91 364 1 001 2 002 3 003 3 432 3 003 2 002
16 15 105 455 1 365 3 003 5 005 6 435 6 435 5 005
17 16 120 560 1 820 4 368 8 008 11 440 12 870 11 440
18 17 136 680 2 380 6 188 12 376 19 448 24 310 24 310
19 18 153 816 3 060 8 568 18 564 31 824 43 758 48 620
20 19 171 969 3 876 11 628 27 132 50 388 75 582 92 378
21 20 190 1 140 4 845 15 504 38 760 77 520 125 970 167 960
22 21 210 1 330 5 985 20 349 54 264 116 280 203 490 293 930
23 22 231 1 540 7 315 26 334 74 613 170 544 319 770 497 420
24 23 253 1 771 8 855 33 649 100 947 245 157 490 314 817 190
25 24 276 2 024 10 626 42 504 134 596 346 104 735 471 1 307 504
26 25 300 2 300 12 650 53 130 177 100 480 700 1 081 575 2 042 975
27 26 325 2 600 14 950 65 780 230 230 657 800 1 562 275 3 124 550
28 27 351 2 925 17 550 80 730 296 010 888 030 2 220 075 4 686 825
29 28 378 3 276 20 475 98 280 376 740 1 184 040 3 108 105 6 906 900
30 29 406 3 654 23 751 118 755 475 020 1 560 780 4 292 145 10 015 005

Hence, complete enumeration is approximately O((L−1)(H−1)/(H−1)!) in time, which is much less than for the general case where the time complexity is approximately O(HL/H!).

Partitioning optimization

For contiguous partitioning with small values of L and H, the size of the problem is not subject to such a combinatorial explosion as in the general case (compare Tables 1 and 2). For instance, for L=22 and H=5, there exist only 5985 distinct partitions, which represents a small problem size (to be compared with 19137821912055 in the general case). Hence, for small values of L and H, we can find a globally optimal partition by exhaustive construction of all distinct contiguous partitions (complete enumeration). For this purpose, an iterative algorithm based on nested loop simulations is described in this section. First, we provide some basic elements to memorize, access and browse a partition of elements. Next, with a pedagogical purpose, we progress step-by-step toward an algorithm that allows browsing of the set PL,H in an exhaustive way, regardless of the value of H. A globally optimal partition P* is obtained by evaluating the objective function for each admissible partition and storing the (first) best one encountered. When the set of contiguous partitions to be considered is not too large, it is thus possible to find, in a reasonable computing time, a globally optimal partition for an objective function of any kind under any set of constraints.

Notation

Algorithms (procedures or functions) are given as pseudocode, with classical control structures. There are three possible passing modes for a procedure parameter depending on whether it is only on input (“in” mode; its value remains unchanged), only on output (“out” mode; its value is defined within the procedure) or both on input/output (“in-out” mode; its value is modified within the procedure). We put a down-arrow, an up-arrow or a down-up-arrow above a parameter’s symbol for specifying in, out, and in-out passing modes, respectively. By definition, all parameters of a function are in input-only passing mode, and therefore down-arrows will be omitted.

Data structures for partitions of elements

In this section, we address the issue of representing a partition of any set of elements U of size N. A partition of U into H classes Uh of sizes Nh may be defined as:

U=⋃h∈HUhwithUh∩Uh′=⌀,h≠h′∈HandN=∑h∈HNh

with the sequence of class indices H=(h1,h2,…,hj,…,hH) with hj>0 for j=1,2,…,H. Without loss of generality, in what follows, it is required that the sequence of indices be defined as hj=hj−1+1 with h1=1, that is H=(1,2,…,H), which can be obtained by simple recoding of the initial indices.

From an operational perspective, at least three simple (equivalent) representations are possible for a set partition (Fig. 1): (i) a membership vector C giving the class of each element; (ii) a (N×H) binary matrix Z where each column is a membership indicator corresponding to a class; and (iii) a composite tabular data structure with an indirection vector V for the elements and a (H×2) table A giving, for each class, the first and last entries in vector V. In what follows, the composite tabular data structure (A,V) is termed a table of classes. One can use any of these representations depending on the context. For other representations, the reader is referred to [12, pp. 62–63]; [25]; [21, p. 416] and [24, Sec. 3.2].

Fig. 1.

Fig. 1

Three simple (equivalent) representations for a set of N elements partitioned into H classes (here H=4). C is a membership vector giving the class of each element. Z is a (N×H) binary matrix where each column is a membership indicator corresponding to a class. We introduce a composite tabular data structure with a (H×2) table A giving, for each class, the first and last entries in an indirection vector V for the elements. For instance, for class h=2, we read between entries 3 and 6 in vector V and entries 1,2,6,10 in vector C. We term the composite tabular data structure a table of classes.

As functionalities, classically, we have to perform two operations: (i) accessing the class of an element and (ii) browsing the elements of a class.

Vector C allows performing operation (i) in O(1) time and operation (ii) in O(N) time. With table Z, operation (i) is in O(H) time, and operation (ii) is in O(N) time, at the cost of a higher memory occupation (except manipulating data at the bit level). The table of classes (A,V) allows performing operation (ii) in O(1) time at the cost of preprocessing in O(N) time and a memory space only slightly larger than that occupied by C (with H≪N). The preliminary processing that allows building the table of classes from C is described by Algorithm 1. Note that from the table of classes (A,V), one can reconstruct vector C in O(N) time (see Fig. 1 and Algorithm 2).

Algorithm 1.

Algorithm 1

Building the table of classes.

Algorithm 2.

Algorithm 2

Reconstructing the class membership vector.

Simulating k nested loops

Consider a situation where it is necessary to vary the values of indices ij such that ℓj≤ij≤uj (j=1,2,…,k). If k is known in advance, we can vary the indices using k nested loops. Without loss of generality, for the following explicit examples, we use k=3. We obtain Algorithm 3. When k is high, writing nested loops becomes quite cumbersome but remains possible, at least in principle. In practice, programming languages only allow an arbitrarily given number of loop nesting levels (the maximum allowed depends on the implementation of computer languages, for instance, 20 in Python, 256 in Visual Basic or Visual C++, 512 in Intel FORTRAN, etc.). Finally, if k is not known in advance, then it becomes impossible to vary the indices using nested loops, as in Algorithm 3. A solution is to simulate nested loops. For example, for k=3, we can propose Algorithm 4. However, we can see that we have indeed eliminated loop nesting, but this time at the cost of test nesting. To simulate any number k of nested loops, we must therefore substitute a loop for the nested tests. This can be done as in Algorithm 5.

Algorithm 3.

Algorithm 3

Writing nested loops (k=3).

Algorithm 4.

Algorithm 4

Simulating nested loops (k=3).

Algorithm 5.

Algorithm 5

Simulating nested loops (any k).

Now, consider a situation we have termed nested loops with incremental lower bounds, where the lower bounds of the indices are written as ℓ1=1 and ℓj=ij−1+1 for j=2,…,k. Initially, we have ℓj=j for j=1,…,k. Note that we must have uj−1<uj for j=2,…,k. For the case k=3, for instance, nested loops are written as in Algorithm 6. Here, again, we can simulate the nesting of loops in the spirit of Algorithm 4. However, it is necessary to initialize an index of level j after the index of level j−1 has been incremented, which gives Algorithm 7. Finally, by initializing the indices in a second step, according to Algorithm 5, the generalization results are given in Algorithm 8.

Algorithm 6.

Algorithm 6

Writing nested loops with incremental lower bounds (k=3).

Algorithm 7.

Algorithm 7

Simulating nested loops with incremental lower bounds (k=3).

Algorithm 8.

Algorithm 8

Simulating nested loops with incremental lower bounds (any k).

Optimal partitioning

Let C* be a globally optimal partition, that is, an instance of vector C corresponding to J*. As an example of constraint, in what follows, we impose that an admissible partition is such that Nh≥b for h=1,…,H, where b≥1 is a minimum class size. Note that if b is set too high, it can happen that no partition is admissible.

For H=5, for example, Algorithm 9 provides the optimal partitioning of the set of values L into contiguous classes by complete enumeration and evaluation of all the admissible partitions. To generalize Algorithm 9 to any H<L, we need to simulate the nesting of any number of loops whose lower bounds are incremental, which can be done using Algorithm 8. From Algorithms 8 and 9, we derive the general version of the contiguous partitioning algorithm for H<L (Algorithm 10).

Algorithm 9.

Algorithm 9

Optimal partitioning of Nx-values into 5 classes.

Algorithm 10.

Algorithm 10

Optimal partitioning of Nx-values into H classes.

Method validation

Validation consists of checking that the computer implementations of the algorithms return correct results. The validation of the algorithms themselves would require formal proofs, a subject far beyond the scope of this article.

The illustrative examples used in this section can be useful to readers for checking their own computer implementations in the programming language of their choice.

Simulating k nested loops

Regarding the simulation of nested loops, the validation stage is straightforward. Without loss of generality, let k=3. In that case, the number of distinct triplets of indices is simply:

∑i1=ℓ1u1∑i2=ℓ2u2∑i3=ℓ3u31=(u1−ℓ1+1)(u2−ℓ2+1)(u3−ℓ3+1) (8)

Empirical validation can merely consist of checking that (i) we obtain the correct number of triplets and (ii) the implementations of Algorithm 3, Algorithm 4 and 5 return the same triplets.

Consider a small illustrative example with ℓ1=1, ℓ2=2, ℓ3=3, u1=3, u2=4 and u3=5. According to expression (8), the number of distinct triplets is 27. Table 3 illustrates the correctness and equivalence of the three procedures.

Table 3.

Triplets for k=3 (ordinary) nested loops, with ℓi=i and ui=2+i for i=1,2,3.

Algorithm 3 Algorithm 4 Algorithm 5
{1,2,3} {1,2,3} {1,2,3}
{1,2,4} {1,2,4} {1,2,4}
{1,2,5} {1,2,5} {1,2,5}
{1,3,3} {1,3,3} {1,3,3}
{1,3,4} {1,3,4} {1,3,4}
{1,3,5} {1,3,5} {1,3,5}
{1,4,3} {1,4,3} {1,4,3}
{1,4,4} {1,4,4} {1,4,4}
{1,4,5} {1,4,5} {1,4,5}
{2,2,3} {2,2,3} {2,2,3}
{2,2,4} {2,2,4} {2,2,4}
{2,2,5} {2,2,5} {2,2,5}
{2,3,3} {2,3,3} {2,3,3}
{2,3,4} {2,3,4} {2,3,4}
{2,3,5} {2,3,5} {2,3,5}
{2,4,3} {2,4,3} {2,4,3}
{2,4,4} {2,4,4} {2,4,4}
{2,4,5} {2,4,5} {2,4,5}
{3,2,3} {3,2,3} {3,2,3}
{3,2,4} {3,2,4} {3,2,4}
{3,2,5} {3,2,5} {3,2,5}
{3,3,3} {3,3,3} {3,3,3}
{3,3,4} {3,3,4} {3,3,4}
{3,3,5} {3,3,5} {3,3,5}
{3,4,3} {3,4,3} {3,4,3}
{3,4,4} {3,4,4} {3,4,4}
{3,4,5} {3,4,5} {3,4,5}

In the case of nested loops with incremental lower bounds, for k=3, the number of distinct triplets of indices may be written as:

∑i1=1u1∑i2=i1+1u2∑i3=i2+1u31=16u1(u1(u1−3(u3−1))+u2(3(2u3−u2−1))−3u3+2) (9)

The empirical validation is carried out in the same way as previously. We check that (i) we obtain the correct number of triplets and (ii) the implementations of Algorithm 6, Algorithm 7 and 8 return the same triplets.

Consider again a small illustrative example, with u1=4, u2=5 and u3=6. According to expression (9), the number of distinct triplets is 20. Table 4 illustrates the correctness and equivalence of the three procedures.

Table 4.

Triplets for k=3 nested loops with incremental lower bounds, with ui=3+i for i=1,2,3.

Algorithm 6 Algorithm 7 Algorithm 8
{1,2,3} {1,2,3} {1,2,3}
{1,2,4} {1,2,4} {1,2,4}
{1,2,5} {1,2,5} {1,2,5}
{1,2,6} {1,2,6} {1,2,6}
{1,3,4} {1,3,4} {1,3,4}
{1,3,5} {1,3,5} {1,3,5}
{1,3,6} {1,3,6} {1,3,6}
{1,4,5} {1,4,5} {1,4,5}
{1,4,6} {1,4,6} {1,4,6}
{1,5,6} {1,5,6} {1,5,6}
{2,3,4} {2,3,4} {2,3,4}
{2,3,5} {2,3,5} {2,3,5}
{2,3,6} {2,3,6} {2,3,6}
{2,4,5} {2,4,5} {2,4,5}
{2,4,6} {2,4,6} {2,4,6}
{2,5,6} {2,5,6} {2,5,6}
{3,4,5} {3,4,5} {3,4,5}
{3,4,6} {3,4,6} {3,4,6}
{3,5,6} {3,5,6} {3,5,6}
{4,5,6} {4,5,6} {4,5,6}

Optimal partitioning

In this section, (i) we verify that we obtain the correct number of distinct partitions; (ii) we check that the implementations of Algorithms 9 and 10 return the same partitions; (iii) we provide two examples for least-squares partitioning; (iv) we provide an example for optimal stratification; and (v) we examine the question of computing time.

First, we consider a small illustrative example where X=(1,9,7,5,3,1,9,7,5,3,11,13,9) and H=5. The number of distinct values is L=7. From expression (4), we should obtain |P7,5|=15 distinct partitions (for b=1). This is what Table 5 shows.

Table 5.

Partition into H=5 classes, expressed as contiguous blocks of x-values (for b=1). r(P) is the rank of the partition.

r(P) Algorithm 9 Algorithm 10
1 1|3|5|7|9,11,13 1|3|5|7|9,11,13
2 1|3|5|7,9|11,13 1|3|5|7,9|11,13
3 1|3|5|7,9,11|13 1|3|5|7,9,11|13
4 1|3|5,7|9|11,13 1|3|5,7|9|11,13
5 1|3|5,7|9,11|13 1|3|5,7|9,11|13
6 1|3|5,7,9|11|13 1|3|5,7,9|11|13
7 1|3,5|7|9|11,13 1|3,5|7|9|11,13
8 1|3,5|7|9,11|13 1|3,5|7|9,11|13
9 1|3,5|7,9|11|13 1|3,5|7,9|11|13
10 1|3,5,7|9|11|13 1|3,5,7|9|11|13
11 1,3|5|7|9|11,13 1,3|5|7|9|11,13
12 1,3|5|7|9,11|13 1,3|5|7|9,11|13
13 1,3|5|7,9|11|13 1,3|5|7,9|11|13
14 1,3|5,7|9|11|13 1,3|5,7|9|11|13
15 1,3,5|7|9|11|13 1,3,5|7|9|11|13

With the admissibility constraint b=2, again, the two procedures return the same five partitions (Table 6). Recall that b is defined with respect to the number of elements, not to the number of distinct x-values. Note that for b>2, no partition can be obtained with this small example.

Table 6.

Partition into H=5 classes, expressed as contiguous blocks of x-values (for b=2). r(P) is the rank of the partition among the admissible ones.

r(P) Algorithm 9 Algorithm 10
1 1|3|5|7|9,11,13 1|3|5|7|9,11,13
2 1|3|5|7,9|11,13 1|3|5|7,9|11,13
3 1|3|5,7|9|11,13 1|3|5,7|9|11,13
4 1|3,5|7|9|11,13 1|3,5|7|9|11,13
5 1,3|5|7|9|11,13 1,3|5|7|9|11,13

⋄ Least-squares partitioning

A classical objective function used in clustering derives from the total inertia decomposition:

T=∑i=1N(xi−X¯)2=∑h=1H∑i∈Uh(xi−X¯)2=∑h=1H∑i∈Uh(xi−X¯h)2︸W(P)+∑h=1HNh(X¯h−X¯)2︸B(P) (10)

with the overall mean:

X¯=1N∑i∈Uxi (11)

the intraclass mean (for h=1,…,H):

X¯h=1Nh∑i∈Uhxi (12)

and where W(P) and B(P) are the within- and between-class inertia, respectively. Obtaining the most compact classes is equivalent to finding a globally optimal partition P* that minimizes W(P), or equivalently, that maximizes B(P) (since T is constant); formally,

B*=B(P*)=arg maxP∈SL,HB(P) (13)

where the objective function B(P) translates into Algorithm 11.

Algorithm 11.

Algorithm 11

Between-class inertia for partition C of Nx-values into H classes.

For our small illustrative example, we have T≃171.07692. For H=5 and the admissibility constraint b=2, the global optimum is such that W(P)+B(P)≃6.00000+165.07692. This small example illustrates that there is not necessarily a single optimal partition, although the optimum for the objective function is unique. Indeed, we have three optimal partitions (see Table 7):

  • •

    ((1,1),(3,3),(5,5,7,7),(9,9,9),(11,13)) with W=0+0+4+0+2;

  • •

    ((1,1),(3,3,5,5),(7,7),(9,9,9),(11,13)) with W=0+4+0+0+2;

  • •

    ((1,1,3,3),(5,5),(7,7),(9,9,9),(11,13)) with W=4+0+0+0+2.

Table 7.

Partition into H=5 classes, expressed as arrays C (for b=2). W and B are the within- and between-class inertia, respectively.

X C(1) C(2) C(3) C(4) C(5)
1 1 1 1 1 1
1 1 1 1 1 1
3 2 2 2 2 1
3 2 2 2 2 1
5 3 3 3 2 2
5 3 3 3 2 2
7 4 4 3 3 3
7 4 4 3 3 3
9 5 4 4 4 4
9 5 4 4 4 4
9 5 4 4 4 4
11 5 5 5 5 5
13 5 5 5 5 5

W 12.80000 6.80000 6.00000 6.00000 6.00000
B 158.27692 164.27692 165.07692 165.07692 165.07692

As another example, we consider L=1000 and H=3, a situation for which the number of distinct contiguous partitions is |P1000,3|=498501. To examine this situation, we draw N=1000 random deviates from a uniform distribution on interval ]0,1[ (no value is equal to another, so L=N). For the reader to replicate the example, we used the R function runif with prior initialization set.seed(2023).

In the case of univariate least-squares partitioning, the best method to find the globally optimal solution is provided by the W.D. Fisher’s algorithm [11]. For an efficient computer implementation of this algorithm in FORTRAN 66, we refer the reader to [14, pp. 141–142]. The method is also implemented in the R function classIntervals defined in package classInt, using option style=“fisher” (see https://CRAN.R-project.org/package=classInt). Hence, we can check that we obtain exactly the same result when comparing the solutions provided by (i) the implementations of Algorithms 10 and 11 and (ii) Fisher’s algorithm. This is a form of external validation.

With x containing the N simulated values, the R command is written as:

result <- classIntervals(x,style=“fisher”,n=3)

For our example, with total inertia T≃81.06425, we obtain in both cases (i) and (ii) the decomposition W(P)+B(P)≃9.13947+71.92478. We obtain classes of respective sizes N1=360, N2=336 and N3=304. Note that the interval class breaks returned by classIntervals (memorized in result$brks) are the lowest x-value (lower bound of class h=1), the midvalue between the last x-value of class h=1 and the first x-value of class h=2, and the highest x-value (upper bound of class h=3).

⋄ Optimal stratification

Consider a finite population U stratified into H classes Uh of sizes Nh (h=1,…,H). Let y be a survey variable for which the population mean is:

Y¯=1N∑i∈Uyi=∑h∈HWhY¯h (14)

with Wh=Nh/N being the weight of stratum h in the population and the corresponding stratum mean:

Y¯h=1Nh∑i∈Uhyi (15)

Let s be a sample of size n partitioned as s=∪h∈Hsh where sh of size nh is drawn from Uh, independently for h=1,…,H. The within-stratum sample size is nh=n×ah, where the set of ah (for h=1,…,H) defines an allocation rule. In what follows, we consider the case where sh is drawn from Uh by simple random sampling without replacement. In that case, an unbiased estimator of the finite population mean Y¯ is written simply as:

Y¯^=∑h∈HWhy¯h (16)

with

y¯h=1nh∑i∈shyi (17)

The sampling variance of estimator (16) is:

V(Y¯^)=1N2∑h∈HNh(Nh−nh)Sh2nh (18)

with Sh2 being the within-stratum variance defined as:

Sh2=1Nh−d∑i∈Uh(yi−Y¯h)2 (19)

where d=1.

Let x be an auxiliary variable closely related to the survey variable y, which serves as a stratification variable. In what follows, we assume y≡x; that is, we do not distinguish the stratification variable from the survey variable.

A classical objective in stratified random sampling of a finite population is to minimize the overall sample size for a prescribed value of the coefficient of variation for Y¯ (denoted here as c), that is, to minimize:

n(P)=∑h∈HWh2Sh2/ahc2Y¯2N−1∑h∈HWhSh2 (20)

Here, we use the well-known optimal allocation rule for the mean estimator, that is:

ah=NhSh∑h∈HNhSh (21)

Obtaining the optimal stratification is equivalent to finding a globally optimal partition P* that minimizes the overall sample size n, formally:

n*=n(P*)=arg minP∈SL,Hn(P) (22)

where the objective function n(P) translates into Algorithm 12. Note that in this algorithm, one-pass computation of the within-strata sum-of-squares is performed using the numerically stable updating formula proposed in [32] (see also [31, Sec. 2.4.4]). As we want to minimize objective function (20), at Line 38 of Algorithm 10, the condition has to be reversed (J<J*), and at Line 14, the initialization must be J*←MAX where max is the maximum finite value for the floating-point type used in the computer implementation of the algorithm (i.e., with single-, double-, extended- or quadruple-precision floating-point numbers).

Algorithm 12.

Algorithm 12

Sample size for stratification C of Nx-values into H strata. v=c2Y¯2, d∈{0,1}.

Complete enumeration for optimal univariate stratification is also implemented in the R function strata.LH defined in package stratification [3]. Hence, we can check that we obtain exactly the same result when comparing the solutions provided by (i) the implementations of Algorithms 10 and 12 and (ii) the R function strata.LH. Again, this is a form of external validation.

Note that to reproduce the results provided by the R function strata.LH, we need to use d=0 in expression (19) and therefore also as an argument for Algorithm 12.

We used the same example as in [3, Sec. 7.1], with N=357, L=200 and H=2 (|P200,2|=199). As an admissibility constraint, we also set b=2. The targeted coefficient of variation was c=0.05. With x containing the values of the stratification variable, the R command is written as:

result <- strata.LH(x=USbanks,CV=0.05,Ls=2,alloc=c(0.5,0,0.5))

We obtain exactly the same (unrounded) n-values and hence the same optimal value n*≃45.62795, returned by min(result$sol.detail$opti.nhnonint), corresponding to the partition of rank r(P)=124 among the 197 that were admissible (see Table 8).

Table 8.

Values of the (unrounded) sample size n for the first five and last five partitions, and for the optimal one (bold value). r(P) is the rank of the partition among the admissible ones.

r(P) Algorithms 10 and 12 Function strata.LH
1 157.03203 157.03203
2 155.23025 155.23025
3 152.23572 152.23572
4 151.04599 151.04599
5 149.27618 149.27618
⋮ ⋮ ⋮
124 45.62795 45.62795
⋮ ⋮ ⋮
193 127.74584 127.74584
194 132.07775 132.07775
195 140.99220 140.99220
196 145.14956 145.14956
197 149.48127 149.48127

Note that the implementation of the optimal stratification by complete enumeration in the R function strata.LH is not efficient since the exhaustive list of combinations is memorized. For each combination of the list, the admissibility constraint is evaluated, and when the partition is admissible, the objective function is calculated. Memorizing all the combinations is useless, but it allows the authors of the package stratification to delegate the combination enumeration to the R function combn from package utils. In contrast, Algorithm 10 is standalone and more efficient.

⋄ Computing time

Many combinatorial optimization problems are subject to combinatorial explosion, so complete enumeration is usually dismissed as an unfeasible approach in practice. For optimal contiguous partitioning, there are two aspects to consider. First, the combinatorial enumeration of contiguous partitions is more favorable than for the general problem of set partitioning (i.e., when the elements cannot be ordered), which allows considering the complete enumeration for greater numbers of elements and classes than in the general case. Second, what is deemed to be a reasonable problem size to be handled by complete enumeration obviously depends on the performance of the programming language implementations and computers at the time of writing. In this paper, computing time refers to using an efficient compiled programming language (such as FORTRAN, Pascal/Delphi, PowerBASIC or C/C++), double-precision floating-point numbers and a widespread processor, namely, the Intel® Core™ i5-2500 3.30 GHz CPU. In this section, we provide orders of magnitude in actual computing time.

One must distinguish between the time it takes to run Algorithm 10 for building |PL,H| contiguous partitions and the total computing time required when a given objective function is optimized. For example, building approximately 10 million contiguous partitions (e.g., for L=30 and H=10, see Table 2) is done in only a few seconds. It takes about one minute to build approximately 120 million contiguous partitions (i.e., for instance, with L=31 and H=14 or with L=43 and H=9). Actually, the total computational time load is dominated by the evaluation of the objective function. With an objective function that is quickly calculated, we can consider complete enumeration for several dozen or hundreds of millions of contiguous partitions. For reference, for the least-squares partitioning example with L=1000 and H=3 (|P1000,3|=498501), the total computing time is less than 6 seconds. For L=10000 and H=3 (|P10000,3|=49985001), the total computing time is approximately 90 minutes. In some cases, the computation of the objective function may be time demanding (e.g., when using a Monte Carlo method). Obviously, for a constant computing time, the more time-consuming the objective function evaluation is, the smaller the problem size can be.

Additional information

In the case of least-squares partitioning, the additive nature of the objective function allows an efficient optimization method based on dynamic programming [11]. It is the same for other objective functions as long as they are additive [16]. However, in this article, we want the objective function to be of any kind (in particular not necessarily additive) and a set of constraints to be taken into account. As we want a completely general method, we have to abandon the idea of an algorithm with pseudopolynomial time complexity since then, finding a globally optimal partition requires complete enumeration.

When complete enumeration becomes computationally prohibitive and no algorithm exists for providing a globally optimal partition within acceptable computing time, alternative approaches offering good partitions in a reasonable amount of time are needed, such as stochastic heuristics. For instance, in the survey sampling literature devoted to the optimal stratification issue, a random search algorithm was proposed in [22].

Our motivating application for optimal partitioning by complete enumeration is the stratification of spatial sampling units in a multispecies survey program [2]. In this application, 25 species of birds are surveyed in European France using a stratified two-stage sampling design. The population to be stratified into H=5 strata is a collection of 10 km × 10 km grid cells where the presence of at least one species is attested. Stratification should maximize the sampling coverage probability of spatial distributions for most species (see [2] for more details). The sampling effort allocation aims to oversample the most species-rich grid cells. In the richest cells, the presence of L=22 species is attested. The problem is simplified in that it is univariate (the variable is the number of species). For the sake of consistency, grid cells with the same number of species should belong to the same stratum. Thus, finally, the problem is not expressed in terms of partitioning the grid cells but in terms of partitioning the (sorted) values of the number of species per grid cell; each grid cell will simply be assigned to the class that contains its number of species. Algorithm 10 allows finding a globally optimal partition very quickly since the objective function has a closed form (see [2]), and there are only |P22,5|=5985 distinct contiguous partitions (see Table 2).

Declaration of Competing Interest

The author declares that he has no known competing financial interests or personal relationships that could have appeared to influence the work reported in this paper.

Acknowledgments

I thank American Journal Experts (AJE) and my colleague Matthieu Guillemain for checking the English of this article. I am grateful to the reviewers for their comments, which provided me with the opportunity to improve the article.

Appendix

To obtain a closed form of expression (5), we proceed by induction. The demonstration is algebraically straightforward although somewhat cumbersome. Note first that we have:

∑i=1ni=12n(n+1)∑i=1ni(i+1)=13n(n+1)(n+2)∑i=1ni(i+1)(i+2)=14n(n+1)(n+2)(n+3) (A.1)

that can be generalized into:

∑i=1n∏k=0p(i+k)=1p+2∏k=0p+1(n+k) (A.2)

We also have:

∑i=jni=12n(n+1)−12(j−1)j∑i=jni(i+1)=13n(n+1)(n+2)−13(j−1)j(j+1)∑i=jni(i+1)(i+2)=14n(n+1)(n+2)(n+3)−14(j−1)j(j+1)(j+2) (A.3)

that can be generalized into:

∑i=jn∏k=0p(i+k)=1p+2∏k=0p+1(n+k)−1p+2∏k=−1p(j+k) (A.4)

Expanding the summations in expression (5) from right to left (i.e., from the inner to the outer loop), we have, for H=2:

P(L,2)=∑i1=1L−11=L−1 (A.5)

for H=3:

∑i1=1L−2∑i2=i1+1L−11=∑i1=1L−2(L−1−i1)=∑i1=1L−2(L−1)−∑i1=1L−2i1=(L−1)∑i1=1L−21−∑i1=1L−2i1=(L−1)(L−2)−12(L−1)(L−2)=12(L−1)(L−2)

for H=4:

∑i1=1L−3∑i2=i1+1L−2∑i3=i2+1L−11=∑i1=1L−3∑i2=i1+1L−2(L−1−i2)=∑i1=1L−3[∑i2=i1+1L−2(L−1)−∑i2=i1+1L−2i2]=∑i1=1L−3[(L−1)∑i2=i1+1L−21−∑i2=i1+1L−2i2]=∑i1=1L−3[(L−1)(L−2−i1)−12(L−1)(L−2)+12i1(i1+1)]=∑i1=1L−3(L−1)(L−2−i1)−∑i1=1L−312(L−1)(L−2)+∑i1=1L−312i1(i1+1)=(L−1)∑i1=1L−3(L−2−i1)−12(L−1)(L−2)∑i1=1L−31+12∑i1=1L−3i1(i1+1)=(L−1)[∑i1=1L−3(L−2)−∑i1=1L−3i1]−12(L−1)(L−2)(L−3)+12∑i1=1L−3i1(i1+1)=(L−1)[(L−2)∑i1=1L−31−∑i1=1L−3i1]−12(L−1)(L−2)(L−3)+16(L−1)(L−2)(L−3)=(L−1)[(L−2)(L−3)−12(L−2)(L−3)]−12(L−1)(L−2)(L−3)︸0+16(L−1)(L−2)(L−3)=16(L−1)(L−2)(L−3)

for H=5:

∑i1=1L−4∑i2=i1+1L−3∑i3=i2+1L−2∑i4=i3+1L−11=∑i1=1L−4∑i2=i1+1L−3∑i3=i2+1L−2(L−1−i3)=∑i1=1L−4∑i2=i1+1L−3[∑i3=i2+1L−2(L−1)−∑i3=i2+1L−2i3]=∑i1=1L−4∑i2=i1+1L−3[(L−1)∑i3=i2+1L−21−∑i3=i2+1L−2i3]=∑i1=1L−4∑i2=i1+1L−3[(L−1)(L−2−i2)−12(L−1)(L−2)+12i2(i2+1)]=∑i1=1L−4[∑i2=i1+1L−3(L−1)(L−2−i2)−∑i2=i1+1L−312(L−1)(L−2)+∑i2=i1+1L−312i2(i2+1)]=∑i1=1L−4[(L−1)∑i2=i1+1L−3(L−2−i2)−12(L−1)(L−2)∑i2=i1+1L−31+12∑i2=i1+1L−3i2(i2+1)]=∑i1=1L−4{(L−1)[∑i2=i1+1L−3(L−2)−∑i2=i1+1L−3i2]−12(L−1)(L−2)(L−3−i1)+12[13(L−1)(L−2)(L−3)−13i1(i1+1)(i1+2)]}=∑i1=1L−4{(L−1)[(L−2)∑i2=i1+1L−31−∑i2=i1+1L−3i2]}−∑i1=1L−412(L−1)(L−2)(L−3−i1)+∑i1=1L−416(L−1)(L−2)(L−3)−∑i1=1L−416i1(i1+1)(i1+2)=(L−1)∑i1=1L−4{[(L−2)(L−3−i1)−∑i2=i1+1L−3i2]}−12(L−1)(L−2)∑i1=1L−4L−3−i1+16(L−1)(L−2)(L−3)∑i1=1L−41−16∑i1=1L−4i1(i1+1)(i1+2)=(L−1)∑i1=1L−4[(L−2)(L−3−i1)−12(L−2)(L−3)+12i1(i1+1)]−12(L−1)(L−2)[∑i1=1L−4(L−3)−∑i1=1L−4i1]+16(L−1)(L−2)(L−3)(L−4)−1614(L−1)(L−2)(L−3)(L−4)
=(L−1)[∑i1=1L−4(L−2)(L−3−i1)−∑i1=1L−412(L−2)(L−3)+∑i1=1L−412i1(i1+1)]−12(L−1)(L−2)[(L−3)∑i1=1L−41−12(L−3)(L−4)]+16(L−1)(L−2)(L−3)(L−4)−124(L−1)(L−2)(L−3)(L−4)=(L−1)[(L−2)∑i1=1L−4(L−3−i1)−12(L−2)(L−3)∑i1=1L−41+12∑i1=1L−4i1(i1+1)]−12(L−1)(L−2)[(L−3)∑i1=1L−41−12(L−3)(L−4)]+16(L−1)(L−2)(L−3)(L−4)−124(L−1)(L−2)(L−3)(L−4)=(L−1){(L−2)[∑i1=1L−4(L−3)−∑i1=1L−4i1]−12(L−2)(L−3)(L−4)+1213(L−2)(L−3)(L−4)}−12(L−1)(L−2)[(L−3)(L−4)−12(L−3)(L−4)]+16(L−1)(L−2)(L−3)(L−4)−124(L−1)(L−2)(L−3)(L−4)=(L−1){(L−2)[(L−3)∑i1=1L−41−12(L−3)(L−4)]−12(L−2)(L−3)(L−4)︸0+16(L−2)(L−3)(L−4)}−12(L−1)(L−2)[(L−3)(L−4)−12(L−3)(L−4)]+16(L−1)(L−2)(L−3)(L−4)−124(L−1)(L−2)(L−3)(L−4)=16(L−1)(L−2)(L−3)(L−4)−14(L−1)(L−2)(L−3)(L−4)+16(L−1)(L−2)(L−3)(L−4)−124(L−1)(L−2)(L−3)(L−4)=124(L−1)(L−2)(L−3)(L−4)

We do not go beyond H=5. Hence, we have:

|PL,2|=11(L−1) (A.6)
|PL,3|=11(L−1)12(L−2) (A.7)
|PL,4|=11(L−1)12(L−2)13(L−3) (A.8)
|PL,5|=11(L−1)12(L−2)13(L−3)14(L−4) (A.9)

The expressions obtained for H=2,3,4,5 generalize to:

|PL,H|=∏h=1H−11h(L−h) (A.10)

One may recognize in expression (A.10) the multiplicative form of a binomial coefficient (see, for instance, [20, p. 53, Eq. 3]), that is:

|PL,H|=(L−1H−1) (A.11)

Data availability

No data was used for the research described in the article.

References

  • 1.Arndt J. Springer; Heidelberg, Germany: 2011. Matters Computational: Ideas, Algorithms, Source Code. [Google Scholar]
  • 2.Aubry P., Quaintenne G., Dupuis J., Francesiaz C., Guillemain M., Caizergues A. On using stratified two-stage sampling for large-scale multispecies surveys. Ecol. Inform. 2023 (submitted) [Google Scholar]
  • 3.Baillargeon S., Rivest L.-P. The construction of stratified designs in R with the package stratification. Surv. Methodol. 2011;37:53–65. [Google Scholar]
  • 4.Batagelj V., Korenjak-Černe S., Klavžar S. Dynamic programming and convex clustering. Algorithmica. 1994;11:93–103. [Google Scholar]
  • 5.Bellman R. A note on cluster analysis and dynamic programming. Math. Biosci. 1973;18:311–312. [Google Scholar]
  • 6.Brusco M., Stahl S. Springer; New York, NY, USA: 2005. Branch-and-Bound Applications in Combinatorial Data Analysis. [Google Scholar]
  • 7.Carlitz L. Set partitions. Fibonacci Q. 1976;14:327–342. [Google Scholar]
  • 8.Cohn M., Even S., Menger K., Hooper P. On the number of partitionings of a set of n distinct objects. Am. Math. Monthly. 1962;69:782–785. [Google Scholar]
  • 9.Das S., Abraham A., Konar A. Springer; Berlin, Germany: 2009. Metaheuristic Clustering. [Google Scholar]
  • 10.Duran B., Odell P. Springer; Berlin, Germany: 1974. Cluster Analysis: A Survey. [Google Scholar]
  • 11.Fisher W. On grouping for maximum homogeneity. J. Am. Stat. Assoc. 1958;53:789–798. [Google Scholar]
  • 12.Flajolet P., Sedgewich R. Cambridge University Press; Cambridge, UK: 2009. Analytic Combinatorics. [Google Scholar]
  • 13.Gan G., Ma C., Wu J. SIAM; Philadelphia, Pennsylvania, USA: 2007. Data Clustering: Theory, Algorithms, and Applications. [Google Scholar]
  • 14.Hartigan J. John Wiley & Sons; New York, NY, USA: 1975. Clustering Algorithms. [Google Scholar]
  • 15.Hubert L., Arabie P., Meulman J. SIAM; Philadelphia, Pennsylvania, USA: 2001. Combinatorial Data Analysis: Optimization by Dynamic Programming. [Google Scholar]
  • 16.Hwang F. Optimal partitions. J. Optim. Theory Appl. 1981;34:1–10. [Google Scholar]
  • 17.Jensen R. A dynamic programming algorithm for cluster analysis. Oper. Res. 1969;17:1034–1057. [Google Scholar]
  • 18.Kanungo T., Mount D., Netanyahu N., Piatko C., Silverman R., Wu A. A local search approximation algorithm for k-means clustering. Comput. Geom. Theory Appl. 2004;28:89–112. [Google Scholar]
  • 19.Kaufman L., Rousseeuw P. John Wiley & Sons; Hoboken, New Jersey, USA: 1990. Finding Groups in Data: An Introduction to Cluster Analysis. [Google Scholar]
  • 20.Knuth D. Addison-Wesley; Reading, Massachusetts, USA: 1997. The Art of Computer Programming. Volume 1. Fundamental Algorithms. Third Edition. [Google Scholar]
  • 21.Knuth D. Addison-Wesley; Upper Saddle River, New Jersey, USA: 2011. The Art of Computer Programming, Volume. 4A. Combinatorial Algorithms. Part 1. [Google Scholar]
  • 22.Kozak M. Optimal stratification using random search method in agricultural surveys. Stat. Transit. 2004;6:797–806. [Google Scholar]
  • 23.Kreher D., Stinson D. CRC Press; Boca Raton, Florida, USA: 1999. Combinatorial Algorithms: Generation, Enumeration, and Search. [Google Scholar]
  • 24.Mansour T. CRC Press; Boca Raton, Florida, USA: 2013. Combinatorics of Set Partitions. [Google Scholar]
  • 25.McCullagh P. In: International Encyclopedia of Statistical Science. Lovric M., editor. Springer; Berlin, Germany: 2011. Random permutations and partition models; pp. 1170–1177. [Google Scholar]
  • 26.Nayak A., Stojmenović I. John Wiley & Sons; Hoboken, New Jersey, USA: 2008. Handbook of Applied Algorithms: Solving Scientific, Engineering and Practical Problems. [Google Scholar]
  • 27.Nijenhuis A., Wilf H. Academic Press; New York, NY, USA: 1978. Combinatorial Algorithms: Second Edition. [Google Scholar]
  • 28.Rao M. Cluster analysis and mathematical programming. J. Am. Stat. Assoc. 1971;66:622–626. [Google Scholar]
  • 29.Stanton D., White D. Springer; New York, NY, USA: 1986. Constructive Combinatorics. [Google Scholar]
  • 30.Talbi E.G. John Wiley & Sons; Hoboken, New Jersey, USA: 2009. Metaheuristics: From Design to Implementation. [Google Scholar]
  • 31.Weihs C., Mersmann O., Ligges U. CRC Press; Boca Raton, Florida, USA: 2014. Foundations of Statistical Algorithms: With References to R Packages. [Google Scholar]
  • 32.Youngs E., Cramer E. Some results relevant to choice of sum and sum-of-product algorithm. Technometrics. 1971;13:657–665. [Google Scholar]

Associated Data

This section collects any data citations, data availability statements, or supplementary materials included in this article.

Data Availability Statement

No data was used for the research described in the article.


Articles from MethodsX are provided here courtesy of Elsevier

RESOURCES