ipfs-cluster/monitor/metrics/prob.go
Adrian Lanzafame b0dbcbaa8d
add reference to original prob.go
License: MIT
Signed-off-by: Adrian Lanzafame <adrianlanzafame92@gmail.com>
2019-04-26 12:20:31 +10:00

81 lines
2.9 KiB
Go

/*
Copyright (©) 2015 Timothée Peignier <timothee.peignier@tryphon.org>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Reference of what was originally copied: https://ipfs.io/ipfs/QmeJDSL6g6u4NSuzUqRxZWhyKPJ6wJAqieQpqX5eXPCjj5
*/
package metrics
import (
"math"
"gonum.org/v1/gonum/floats"
)
// phi returns the φ-failure for the given value and distribution.
// Two edge cases that are dealt with in phi:
// 1. phi == math.+Inf
// 2. phi == math.NaN
//
// Edge case 1. is most certainly a failure, the value of v is is so large
// in comparison to the distribution that the cdf function returns a 1,
// which equates to a math.Log10(0) which is one of its special cases, i.e
// returns -Inf. In this case, phi() will return the math.+Inf value, as it
// will be a valid comparison against the threshold value in checker.Failed.
//
// Edge case 2. could be a failure but may not be. phi() will return NaN
// when the standard deviation of the distribution is 0, i.e. the entire
// distribution is the same number, {1,1,1,1,1}. Considering that we are
// using UnixNano timestamps this would be highly unlikely, but just in case
// phi() will return a -1 value, indicating that the caller should retry.
func phi(v float64, d []float64) float64 {
u, o := meanStdDev(d)
phi := -math.Log10(1 - cdf(u, o, v))
if math.IsNaN(phi) {
return -1
}
return phi
}
// cdf returns the cumulative distribution function if the given
// normal function, for the given value.
func cdf(u, o, v float64) float64 {
return ((1.0 / 2.0) * (1 + math.Erf((v-u)/(o*math.Sqrt2))))
}
func meanStdDev(v []float64) (m, sd float64) {
var variance float64
m, variance = meanVariance(v)
sd = math.Sqrt(variance)
return
}
func meanVariance(values []float64) (m, v float64) {
if len(values) == 0 {
return 0.0, 0.0
}
m = floats.Sum(values) / float64(len(values))
floats.AddConst(-m, values)
floats.Mul(values, values)
v = floats.Sum(values) / float64(len(values))
return
}