github.com/gopherd/gonum@v0.0.4/spatial/kdtree/medians_test.go (about)

     1  // Copyright ©2019 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package kdtree
     6  
     7  import (
     8  	"sort"
     9  	"testing"
    10  
    11  	"math/rand"
    12  )
    13  
    14  type ints []int
    15  
    16  func (a ints) Len() int                  { return len(a) }
    17  func (a ints) Less(i, j int) bool        { return a[i] < a[j] }
    18  func (a ints) Slice(s, e int) SortSlicer { return a[s:e] }
    19  func (a ints) Swap(i, j int)             { a[i], a[j] = a[j], a[i] }
    20  
    21  func TestPartition(t *testing.T) {
    22  	rnd := rand.New(rand.NewSource(1))
    23  
    24  	for p := 0; p < 100; p++ {
    25  		list := make(ints, 1e5)
    26  		for i := range list {
    27  			list[i] = rnd.Int()
    28  		}
    29  		pi := Partition(list, rnd.Intn(list.Len()))
    30  		for i := 0; i < pi; i++ {
    31  			if list[i] > list[pi] {
    32  				t.Errorf("unexpected partition sort order p[%d] > p[%d]: %d > %d", i, pi, list[i], list[pi])
    33  			}
    34  		}
    35  		for i := pi + 1; i < len(list); i++ {
    36  			if list[i] <= list[pi] {
    37  				t.Errorf("unexpected partition sort order p[%d] <= p[%d]: %d <= %d", i, pi, list[i], list[pi])
    38  			}
    39  		}
    40  	}
    41  }
    42  
    43  func TestPartitionCollision(t *testing.T) {
    44  	rnd := rand.New(rand.NewSource(1))
    45  
    46  	for p := 0; p < 10; p++ {
    47  		list := make(ints, 10)
    48  		for i := range list {
    49  			list[i] = rnd.Intn(5)
    50  		}
    51  		pi := Partition(list, p)
    52  		for i := 0; i < pi; i++ {
    53  			if list[i] > list[pi] {
    54  				t.Errorf("unexpected partition sort order p[%d] > p[%d]: %d > %d", i, pi, list[i], list[pi])
    55  			}
    56  		}
    57  		for i := pi + 1; i < len(list); i++ {
    58  			if list[i] <= list[pi] {
    59  				t.Errorf("unexpected partition sort order p[%d] <= p[%d]: %d <= %d", i, pi, list[i], list[pi])
    60  			}
    61  		}
    62  	}
    63  }
    64  
    65  func sortSelection(list ints, k int) int {
    66  	sort.Sort(list)
    67  	return list[k]
    68  }
    69  
    70  func TestSelect(t *testing.T) {
    71  	rnd := rand.New(rand.NewSource(1))
    72  
    73  	for k := 0; k < 2121; k++ {
    74  		list := make(ints, 2121)
    75  		for i := range list {
    76  			list[i] = rnd.Intn(1000)
    77  		}
    78  		Select(list, k)
    79  		sorted := append(ints(nil), list...)
    80  		want := sortSelection(sorted, k)
    81  		if list[k] != want {
    82  			t.Errorf("unexpected result from Select(..., %d): got:%v want:%d", k, list[k], want)
    83  		}
    84  	}
    85  }
    86  
    87  func TestMedianOfMedians(t *testing.T) {
    88  	rnd := rand.New(rand.NewSource(1))
    89  
    90  	list := make(ints, 1e4)
    91  	for i := range list {
    92  		list[i] = rnd.Int()
    93  	}
    94  	p := MedianOfMedians(list)
    95  	med := list[p]
    96  	sort.Sort(list)
    97  	var found bool
    98  	for _, v := range list[len(list)*3/10 : len(list)*7/10+1] {
    99  		if v == med {
   100  			found = true
   101  			break
   102  		}
   103  	}
   104  	if !found {
   105  		t.Error("failed to find median")
   106  	}
   107  }
   108  
   109  func TestMedianOfRandoms(t *testing.T) {
   110  	rnd := rand.New(rand.NewSource(1))
   111  
   112  	list := make(ints, 1e4)
   113  	for i := range list {
   114  		list[i] = rnd.Int()
   115  	}
   116  	p := MedianOfRandoms(list, randoms)
   117  	med := list[p]
   118  	sort.Sort(list)
   119  	var found bool
   120  	for _, v := range list[len(list)*3/10 : len(list)*7/10+1] {
   121  		if v == med {
   122  			found = true
   123  			break
   124  		}
   125  	}
   126  	if !found {
   127  		t.Error("failed to find median")
   128  	}
   129  }
   130  
   131  var benchSink int
   132  
   133  func BenchmarkMedianOfMedians(b *testing.B) {
   134  	rnd := rand.New(rand.NewSource(1))
   135  
   136  	for i := 0; i < b.N; i++ {
   137  		b.StopTimer()
   138  		list := make(ints, 1e4)
   139  		for i := range list {
   140  			list[i] = rnd.Int()
   141  		}
   142  		b.StartTimer()
   143  		benchSink = MedianOfMedians(list)
   144  	}
   145  }
   146  
   147  func BenchmarkPartitionMedianOfMedians(b *testing.B) {
   148  	rnd := rand.New(rand.NewSource(1))
   149  
   150  	for i := 0; i < b.N; i++ {
   151  		b.StopTimer()
   152  		list := make(ints, 1e4)
   153  		for i := range list {
   154  			list[i] = rnd.Int()
   155  		}
   156  		b.StartTimer()
   157  		benchSink = Partition(list, MedianOfMedians(list))
   158  	}
   159  }
   160  
   161  func BenchmarkMedianOfRandoms(b *testing.B) {
   162  	rnd := rand.New(rand.NewSource(1))
   163  
   164  	b.StopTimer()
   165  	list := make(ints, 1e4)
   166  	for i := range list {
   167  		list[i] = rnd.Int()
   168  	}
   169  	b.StartTimer()
   170  	for i := 0; i < b.N; i++ {
   171  		benchSink = MedianOfRandoms(list, list.Len()/1e3)
   172  	}
   173  }
   174  
   175  func BenchmarkPartitionMedianOfRandoms(b *testing.B) {
   176  	rnd := rand.New(rand.NewSource(1))
   177  
   178  	b.StopTimer()
   179  	list := make(ints, 1e4)
   180  	for i := range list {
   181  		list[i] = rnd.Int()
   182  	}
   183  	b.StartTimer()
   184  	for i := 0; i < b.N; i++ {
   185  		benchSink = Partition(list, MedianOfRandoms(list, list.Len()/1e3))
   186  	}
   187  }