github.com/fluhus/gostuff@v0.4.1-0.20240331134726-be71864f2b5d/clustering/upgma_test.go (about)

     1  package clustering
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"reflect"
     7  	"testing"
     8  
     9  	"github.com/fluhus/gostuff/gnum"
    10  )
    11  
    12  func TestUPGMA(t *testing.T) {
    13  	points := []float64{1, 4, 6, 10}
    14  	steps := []AggloStep{
    15  		{1, 2, 2},
    16  		{0, 2, 4},
    17  		{2, 3, 19.0 / 3.0},
    18  	}
    19  	agg := upgma(len(points), func(i, j int) float64 {
    20  		return math.Abs(points[i] - points[j])
    21  	})
    22  	if agg.Len() != len(points)-1 {
    23  		t.Fatalf("Len()=%v, want %v", agg.Len(), len(points)-1)
    24  	}
    25  	for i := range steps {
    26  		if step := agg.Step(i); !reflect.DeepEqual(steps[i], step) {
    27  			t.Errorf("Step(%v)=%v, want %v", i, step, steps[i])
    28  		}
    29  	}
    30  }
    31  
    32  func TestUPGMA_more(t *testing.T) {
    33  	points := []float64{1, 3, 8, 12, 20, 28}
    34  	steps := []AggloStep{
    35  		{0, 1, 2},
    36  		{2, 3, 4},
    37  		{1, 3, 8},
    38  		{4, 5, 8},
    39  		{3, 5, 18},
    40  	}
    41  	agg := upgma(len(points), func(i, j int) float64 {
    42  		return math.Abs(points[i] - points[j])
    43  	})
    44  	if agg.Len() != len(points)-1 {
    45  		t.Fatalf("Len()=%v, want %v", agg.Len(), len(points)-1)
    46  	}
    47  	for i := range steps {
    48  		if step := agg.Step(i); !reflect.DeepEqual(steps[i], step) {
    49  			t.Errorf("Step(%v)=%v, want %v", i, step, steps[i])
    50  		}
    51  	}
    52  }
    53  
    54  func BenchmarkUPGMA(b *testing.B) {
    55  	for _, n := range []int{10, 30, 100} {
    56  		b.Run(fmt.Sprint(n), func(b *testing.B) {
    57  			nums := make([]float64, n)
    58  			for i := range nums {
    59  				nums[i] = 1.0 / float64(i+1)
    60  				if i%2 == 0 {
    61  					nums[i] += 10
    62  				}
    63  			}
    64  			b.ResetTimer()
    65  			for i := 0; i < b.N; i++ {
    66  				upgma(n, func(i1, i2 int) float64 {
    67  					return gnum.Abs(nums[i1] - nums[i2])
    68  				})
    69  			}
    70  		})
    71  	}
    72  }
    73  
    74  func FuzzUPGMA(f *testing.F) {
    75  	f.Add(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
    76  	f.Fuzz(func(t *testing.T, a float64, b float64, c float64,
    77  		d float64, e float64, f float64, g float64, h float64, i float64) {
    78  		nums := []float64{a, b, c, d, e, f, g, h, i}
    79  		upgma(len(nums), func(i1, i2 int) float64 {
    80  			return gnum.Abs(nums[i1] - nums[i2])
    81  		})
    82  	})
    83  }