mirror of
https://github.com/gonum/gonum.git
synced 2025-10-05 15:16:59 +08:00

stat/distuv: add WithoutReplacement for sampling from a set of integers without replacement
66 lines
1.4 KiB
Go
66 lines
1.4 KiB
Go
// Copyright ©2017 The gonum Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package sampleuv
|
|
|
|
import (
|
|
"math/rand"
|
|
"testing"
|
|
|
|
"gonum.org/v1/gonum/floats"
|
|
)
|
|
|
|
func TestWithoutReplacement(t *testing.T) {
|
|
for cas, test := range []struct {
|
|
N int
|
|
K int
|
|
Src *rand.Rand
|
|
Trials int
|
|
Tol float64
|
|
}{
|
|
{
|
|
// Test with perm and source.
|
|
N: 10, K: 5, Src: rand.New(rand.NewSource(1)),
|
|
Trials: 100000, Tol: 1e-3,
|
|
},
|
|
{
|
|
// Test without perm and with source.
|
|
N: 10, K: 3, Src: rand.New(rand.NewSource(1)),
|
|
Trials: 100000, Tol: 1e-3,
|
|
},
|
|
} {
|
|
dist := make([]float64, test.N)
|
|
for trial := 0; trial < test.Trials; trial++ {
|
|
idxs := make([]int, test.K)
|
|
WithoutReplacement(idxs, test.N, test.Src)
|
|
|
|
allDiff := true
|
|
for i := 0; i < len(idxs); i++ {
|
|
v := idxs[i]
|
|
for j := i + 1; j < len(idxs); j++ {
|
|
if v == idxs[j] {
|
|
allDiff = false
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if !allDiff {
|
|
t.Errorf("Cas %d: Repeat in sampling. Idxs =%v", cas, idxs)
|
|
}
|
|
for _, v := range idxs {
|
|
dist[v]++
|
|
}
|
|
}
|
|
div := 1 / (float64(test.Trials) * float64(test.K))
|
|
floats.Scale(div, dist)
|
|
want := make([]float64, test.N)
|
|
for i := range want {
|
|
want[i] = 1 / float64(test.N)
|
|
}
|
|
if !floats.EqualApprox(want, dist, test.Tol) {
|
|
t.Errorf("Cas %d: biased sampling. Want = %v, got = %v", cas, want, dist)
|
|
}
|
|
}
|
|
}
|