diff --git a/internal/trace/trace.go b/internal/trace/trace.go index bf5fb50..971706c 100644 --- a/internal/trace/trace.go +++ b/internal/trace/trace.go @@ -101,7 +101,9 @@ func (t *Trace) computeSummary() *Summary { } } if firstSuccess > 0 { - s.ConvergenceRate = float64(firstSuccess) / float64(s.TotalIterations) + // Higher is better: success on the first iteration => 1.0, + // success only on the last iteration => near 0. + s.ConvergenceRate = 1.0 - float64(firstSuccess-1)/float64(s.TotalIterations) } } diff --git a/internal/trace/trace_test.go b/internal/trace/trace_test.go new file mode 100644 index 0000000..1be572c --- /dev/null +++ b/internal/trace/trace_test.go @@ -0,0 +1,52 @@ +package trace + +import "testing" + +func TestConvergenceRateHigherMeansFaster(t *testing.T) { + fast := New([]Iteration{ + {Number: 1, Verification: &Verification{Status: "success"}}, + {Number: 2, Verification: &Verification{Status: "success"}}, + {Number: 3, Verification: &Verification{Status: "fail"}}, + {Number: 4}, + {Number: 5}, + {Number: 6}, + {Number: 7}, + {Number: 8}, + {Number: 9}, + {Number: 10}, + }) + slow := New([]Iteration{ + {Number: 1, Verification: &Verification{Status: "fail"}}, + {Number: 2, Verification: &Verification{Status: "fail"}}, + {Number: 3, Verification: &Verification{Status: "fail"}}, + {Number: 4, Verification: &Verification{Status: "fail"}}, + {Number: 5, Verification: &Verification{Status: "fail"}}, + {Number: 6, Verification: &Verification{Status: "fail"}}, + {Number: 7, Verification: &Verification{Status: "fail"}}, + {Number: 8, Verification: &Verification{Status: "fail"}}, + {Number: 9, Verification: &Verification{Status: "fail"}}, + {Number: 10, Verification: &Verification{Status: "success"}}, + }) + + if fast.Summary.ConvergenceRate != 1.0 { + t.Fatalf("first-try ConvergenceRate = %v, want 1.0", fast.Summary.ConvergenceRate) + } + wantSlow := 1.0 - float64(9)/float64(10) + if slow.Summary.ConvergenceRate != wantSlow { + t.Fatalf("last-try ConvergenceRate = %v, want %v", slow.Summary.ConvergenceRate, wantSlow) + } + if !(fast.Summary.ConvergenceRate > slow.Summary.ConvergenceRate) { + t.Fatalf("expected faster convergence to score higher: fast=%v slow=%v", + fast.Summary.ConvergenceRate, slow.Summary.ConvergenceRate) + } +} + +func TestConvergenceRateNoSuccessIsZero(t *testing.T) { + tr := New([]Iteration{ + {Number: 1, Verification: &Verification{Status: "fail"}}, + {Number: 2, Verification: &Verification{Status: "fail"}}, + }) + if tr.Summary.ConvergenceRate != 0 { + t.Fatalf("ConvergenceRate = %v, want 0 when never successful", tr.Summary.ConvergenceRate) + } +}