Documentation
¶
Overview ¶
Package bigo is a library to generate Big O estimates for real world timings of algorithms and code. Given a collection of counts and timings collected when running code or benchmarks, the library will attempt to Classify which Big O notations most likely match the values.
The library has support for the following Big O classifications:
- O(1) - Constant Time
- O(log (log n)) - Double Log Time
- O(n (log n)) - Log Time
- O((log n)^c) - Polylogarithmic Time
- O(n) - Linear Time
- O(n log* n) - N Log* Time
- O(n log n) - Linearithmic Time
- O(n^2) - Quadratic Time
- O(n^3) - Cubic Time
- O(n^c) - Polynomial Time
- O(2^n) - Exponential Time
- O(n!) - Factorial Time
- O(n^n) - Hyper-Exponential Time
The characterization can be applied to anyset of values whether they are times, bytes, allocations, or any other type.
Underneath the examples directory are subdirectories for each Big O category that contain a variety of example methods and algorithms that are generally considered to fall in a given level along with basic benchmarks that can be used to generate real timing results that can be used.
Index ¶
- Variables
- type BigO
- type Classifier
- func (o *Classifier) AddBenchmarkResult(result testing.BenchmarkResult) error
- func (o *Classifier) AddDataPoint(n int, values ...float64) error
- func (o *Classifier) AddDataPointBig(n int, values ...*big.Float) error
- func (o *Classifier) AddDataPoints(n []int, values [][]float64) error
- func (o *Classifier) AddDataPointsBig(n []int, values [][]*big.Float) error
- func (o *Classifier) Classify() (*Rating, error)
- func (o *Classifier) GetAllRatings() []*Rating
- func (o *Classifier) LoadCSV(path string, header bool, delimiter rune) error
- func (o *Classifier) Summary() string
- type Rating
Constants ¶
This section is empty.
Variables ¶
var ( // Unrated is a BigO instance for when we have not yet rated the data. Unrated = &BigO{ active: false, rank: 0, label: "O(?)", description: "Not Yet Rated", scalingCutoff: 0, floatCutoffMin: 0, floatCutoffMax: 0, funcFloatFloat: nil, funcFloatBig: nil, funcBigBig: nil, } // Constant is a BigO instance for constant time functions. // // Uses special variance-based detection instead of correlation since // constant values have zero variance. Constant = &BigO{ active: true, rank: 1, label: "O(1)", description: "An algorithm with O(1) complexity runs in constant time, regardless of the input size.", floatCutoffMin: math.SmallestNonzeroFloat64, floatCutoffMax: math.MaxFloat64, scalingCutoff: math.MaxInt64, funcFloatFloat: func(_ float64) float64 { return 1 }, funcFloatBig: func(_ float64) *big.Float { return big.NewFloat(1) }, funcBigBig: func(_ *big.Float) *big.Float { return big.NewFloat(1) }, } // InverseAckerman is a BigO instance for the inverse Ackerman function. // Almost as flat a curve as Constant, and quite similar to LogLog. InverseAckerman = &BigO{ active: false, rank: 2, label: "O(α(n))", description: "An algorithm with O(α(n)) complexity has a runtime that grows at the rate of the inverse Ackerman function with the input size.", floatCutoffMin: 1, floatCutoffMax: math.MaxFloat64, scalingCutoff: math.MaxInt64, funcFloatFloat: func(x float64) float64 { return inverseAckermann(int(x)) }, funcFloatBig: func(x float64) *big.Float { return inverseAckermannBig(big.NewFloat(x)) }, funcBigBig: inverseAckermannBig, } // LogLog is a BigO instance for the double log function. LogLog = &BigO{ active: true, rank: 4, label: "O(log log n)", description: "An algorithm with O(log log n) complexity has a runtime that grows logarithmically twice with the input size.", floatCutoffMin: math.Exp(math.Exp(0)), floatCutoffMax: math.MaxFloat64, scalingCutoff: math.MaxInt64, funcFloatFloat: func(x float64) float64 { return math.Log(math.Log(x)) }, funcFloatBig: func(x float64) *big.Float { return bigmath.Log(bigmath.Log(big.NewFloat(x))) }, funcBigBig: func(x *big.Float) *big.Float { return bigmath.Log(bigmath.Log(x)) }, } // Log is a BigO instance for Log complexity functions. Log = &BigO{ active: true, rank: 8, label: "O(log n)", description: "An algorithm with O(log n) complexity has a runtime that grows logarithmically as the input size increases. This often involves dividing the problem in half each time.", floatCutoffMin: math.Exp(0), floatCutoffMax: math.MaxFloat64, scalingCutoff: math.MaxInt64, funcFloatFloat: math.Log, funcFloatBig: func(x float64) *big.Float { return big.NewFloat(math.Log(x)) }, funcBigBig: bigmath.Log, } // Polylogarithmic is a BigO instance for the polylogarithmic function. Polylogarithmic = &BigO{ active: true, rank: 16, label: "O((log n)^c)", description: "An algorithm with O((log n)^c) complexity has a runtime that grows polylogarithmically with the input size.", floatCutoffMin: 1, floatCutoffMax: math.MaxFloat64, scalingCutoff: math.MaxInt64, funcFloatFloat: func(x float64) float64 { return math.Pow(math.Log(x), 4) }, funcFloatBig: func(x float64) *big.Float { return bigmath.Pow(bigmath.Log(big.NewFloat(x)), big.NewFloat(4)) }, funcBigBig: func(x *big.Float) *big.Float { return bigmath.Pow(bigmath.Log(x), big.NewFloat(4)) }, } // Linear is a BigO instance for the linear function. Linear = &BigO{ active: true, rank: 32, label: "O(n)", description: "An algorithm with O(n) complexity has a runtime that grows linearly with the input size.", scalingCutoff: math.MaxInt64, floatCutoffMin: 1, floatCutoffMax: math.MaxFloat64, funcFloatFloat: func(x float64) float64 { return x }, funcFloatBig: big.NewFloat, funcBigBig: func(x *big.Float) *big.Float { return x }, } // NLogStarN is a BigO instance for the n log star n function. NLogStarN = &BigO{ active: true, rank: 64, label: "O(n log* n)", description: "An algorithm with O(n log* n) complexity has a runtime that grows with n times the iterated logarithm of the input size.", floatCutoffMin: 1, floatCutoffMax: math.MaxFloat64, scalingCutoff: math.MaxInt64, funcFloatFloat: func(x float64) float64 { return x * float64(logStarFloat(x)) }, funcFloatBig: func(x float64) *big.Float { logStarVal := logStarBig(big.NewFloat(x)) return new(big.Float).Mul(big.NewFloat(x), big.NewFloat(float64(logStarVal))) }, funcBigBig: func(x *big.Float) *big.Float { logStarVal := logStarBig(x) return new(big.Float).Mul(x, big.NewFloat(float64(logStarVal))) }, } // Linearithmic is a BigO instance for the linearithmic function. Linearithmic = &BigO{ active: true, rank: 128, label: "O(n log n)", description: "An algorithm with O(n log n) complexity typically involves a combination of linear and logarithmic time, often seen in efficient sorting algorithms such as Merge Sort.", scalingCutoff: math.MaxInt64, floatCutoffMin: 1, floatCutoffMax: math.Log(math.MaxFloat64), funcFloatFloat: func(x float64) float64 { return x * math.Log(x) }, funcFloatBig: func(x float64) *big.Float { return bigmath.Log(big.NewFloat(x)).Mul(bigmath.Log(big.NewFloat(x)), big.NewFloat(x)) }, funcBigBig: func(x *big.Float) *big.Float { return bigmath.Log(x).Mul(bigmath.Log(x), x) }, } // Quadratic is a BigO instance for the quadratic function. Quadratic = &BigO{ active: true, rank: 256, label: "O(n^2)", description: "An algorithm with O(n^2) complexity has a runtime that grows quadratically with the input size, often involving nested loops such as Bubble Sort.", scalingCutoff: math.MaxInt64, floatCutoffMin: 1, floatCutoffMax: math.Sqrt(math.MaxFloat64), funcFloatFloat: func(x float64) float64 { return x * x }, funcFloatBig: func(x float64) *big.Float { return new(big.Float).Mul(big.NewFloat(x), big.NewFloat(x)) }, funcBigBig: func(x *big.Float) *big.Float { return new(big.Float).Mul(x, x) }, } // Cubic is a BigO instance for the cubic function. Cubic = &BigO{ active: true, rank: 512, label: "O(n^3)", description: "An algorithm with O(n^3) complexity has a runtime that grows cubically with the input size, often involving three nested loops.", scalingCutoff: math.MaxInt64, floatCutoffMin: 1, floatCutoffMax: math.Cbrt(math.MaxFloat64), funcFloatFloat: func(x float64) float64 { return x * x * x }, funcFloatBig: func(x float64) *big.Float { c := new(big.Float).Mul(big.NewFloat(x), big.NewFloat(x)) return c.Mul(c, big.NewFloat(x)) }, funcBigBig: func(x *big.Float) *big.Float { c := new(big.Float).Mul(x, x) return c.Mul(c, x) }, } // Polynomial is a BigO instance for the polynomial function. Polynomial = &BigO{ active: true, rank: 1024, label: "O(n^c)", description: "An algorithm with O(n^c) complexity has a runtime that grows polynomially with the input size, often involving nested loops.", scalingCutoff: 1000000, floatCutoffMin: 1, floatCutoffMax: math.MaxFloat64, funcFloatFloat: func(x float64) float64 { return math.Pow(x, 4) }, funcFloatBig: func(x float64) *big.Float { return bigmath.PowFloat64(x, 4) }, funcBigBig: func(x *big.Float) *big.Float { return bigmath.Pow(x, big.NewFloat(4)) }, } // Exponential is a BigO instance for the exponential function. Exponential = &BigO{ active: true, rank: 2048, label: "O(2^n)", description: "An algorithm with O(2^n) complexity has a runtime that grows exponentially with the input size, often seen in recursive algorithms solving combinatorial problems.", scalingCutoff: 1000000, floatCutoffMin: 1, floatCutoffMax: 1024.0, funcFloatFloat: math.Exp2, funcFloatBig: func(x float64) *big.Float { return bigmath.PowFloat64(2, x) }, funcBigBig: func(x *big.Float) *big.Float { return bigmath.Pow(big.NewFloat(2), x) }, } // Factorial is a BigO instance for the factorial function. Factorial = &BigO{ active: true, rank: 4096, label: "O(n!)", description: "An algorithm with O(n!) complexity has a runtime that grows factorially with the input size, often seen in problems involving permutations.", scalingCutoff: 1000, floatCutoffMin: 1, floatCutoffMax: 170, funcFloatFloat: func(x float64) float64 { return factorial(int(x)) }, funcFloatBig: func(x float64) *big.Float { return bigmath.FactorialFloat(big.NewFloat(x)) }, funcBigBig: bigmath.FactorialFloat, } // HyperExponential is a BigO instance for the hyper-exponential function. HyperExponential = &BigO{ active: true, rank: 8192, label: "O(n^n)", description: "An algorithm with O(n^n) complexity has a runtime that grows hyper-exponentially with the input size.", scalingCutoff: 500, floatCutoffMin: 1, floatCutoffMax: 141, funcFloatFloat: func(x float64) float64 { return math.Pow(x, x) }, funcFloatBig: func(x float64) *big.Float { return bigmath.PowFloat64(x, x) }, funcBigBig: func(x *big.Float) *big.Float { return bigmath.Pow(x, x) }, } )
var ( // BigOOrdered holds the set of all BigO instances in rank order. BigOOrdered = []*BigO{} )
Functions ¶
This section is empty.
Types ¶
type BigO ¶
type BigO struct {
// contains filtered or unexported fields
}
BigO is used to describe the complexity class of an algorithm, which represents how the runtime or space requirements of an algorithm grow as the input size grows.
func (*BigO) Description ¶
Description returns the description of this BigO.
func (*BigO) Rate ¶
Rate generates the ranking for this particular BigO using its defined cutoffs and mapping functions.
To try to make some of the math easier, we scale the incoming values by the smallest N in the data so that the comparison may hopefully stay in the float64 range.
Non-positive input sizes are filtered out before analysis.
type Classifier ¶
type Classifier struct {
// contains filtered or unexported fields
}
Classifier is used to Classify a set of data points to find the rating they are most likely to correspond to.
func (*Classifier) AddBenchmarkResult ¶
func (o *Classifier) AddBenchmarkResult(result testing.BenchmarkResult) error
AddBenchmarkResult adds the result of a benchmark test to the data. It extracts the nanoseconds per operation from the BenchmarkResult and adds it as a data point using the number of iterations (N) as the input size. This method provides seamless integration with Go's built-in benchmarking system.
The timing data is converted from nanoseconds to a float64 value representing the average execution time per operation. Non-positive iteration counts are ignored.
Usage example:
result := testing.Benchmark(func(b *testing.B) {
for i := 0; i < b.N; i++ {
// your algorithm here
}
})
classifier.AddBenchmarkResult(result)
func (*Classifier) AddDataPoint ¶
func (o *Classifier) AddDataPoint(n int, values ...float64) error
AddDataPoint adds the given values to the data. Non-positive input sizes (n <= 0) are ignored and not added to the dataset.
func (*Classifier) AddDataPointBig ¶
func (o *Classifier) AddDataPointBig(n int, values ...*big.Float) error
AddDataPointBig adds the given values to the data. Non-positive input sizes (n <= 0) are ignored and not added to the dataset.
func (*Classifier) AddDataPoints ¶
func (o *Classifier) AddDataPoints(n []int, values [][]float64) error
AddDataPoints adds all the data points and associated values.
func (*Classifier) AddDataPointsBig ¶
func (o *Classifier) AddDataPointsBig(n []int, values [][]*big.Float) error
AddDataPointsBig adds all the data points and associated values.
func (*Classifier) Classify ¶
func (o *Classifier) Classify() (*Rating, error)
Classify is used to Classify the data so far and determine the most Big O fit. Can be run as often as needed when more data are added.
Common errors that can occur here are lack of distinct data points to be able to analyzye, or errors in a specific BigO test.
For every distinct N value, the values stored for it are averaged to get a working value. The assumption in this package is that the user will do more than a single run of their code to get real world timing results, so we average all the run values for a given N.
TODO(rsned): Add support for the big.Float values as well. TODO(rsned): If there are at least 30-50 values for a given N, then we can run some basic stats tests on the data points to test for outliers in the data . TODO(rsned): If the number of values for a given N are large enough, should we include the option to discard the outlier in the values?
func (*Classifier) GetAllRatings ¶
func (o *Classifier) GetAllRatings() []*Rating
GetAllRatings returns a copy of all the ratings generated by the most recent Classify() call. Returns nil if Classify() has not been called yet. The ratings are sorted by BigO rank (lowest rank first). The returned slice is a copy and can be safely modified without affecting internal state.
func (*Classifier) LoadCSV ¶
func (o *Classifier) LoadCSV(path string, header bool, delimiter rune) error
LoadCSV loads the data from a 2-column delimiter separated file and adds the values. The header parameter controls whether the first line of the file is a header or not and should be skipped. If an error occurred, no data will be loaded. Any errors encountered are returned. Non-positive input sizes are automatically filtered out during loading.
func (*Classifier) Summary ¶
func (o *Classifier) Summary() string
Summary returns a longer form view of the results as a formatted text blob.
type Rating ¶
type Rating struct {
// contains filtered or unexported fields
}
Rating pairs up a BigO and the score it received in the current processing.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package examples contains a collection of example algorithms and methods and the Big O complexity they are generally associated with.
|
Package examples contains a collection of example algorithms and methods and the Big O complexity they are generally associated with. |
|
constant
Package constant contains implementations of algorithms with O(1) constant time complexity.
|
Package constant contains implementations of algorithms with O(1) constant time complexity. |
|
cubic
Package cubic contains implementations of algorithms with O(n³) cubic time complexity.
|
Package cubic contains implementations of algorithms with O(n³) cubic time complexity. |
|
datatypes/collection
Package collection provides generic collection data structures optimized for Big O complexity analysis and education.
|
Package collection provides generic collection data structures optimized for Big O complexity analysis and education. |
|
datatypes/tree
Package tree provides advanced tree data structure implementations for efficient range queries, updates, and specialized operations.
|
Package tree provides advanced tree data structure implementations for efficient range queries, updates, and specialized operations. |
|
exponential
Package exponential contains implementations of algorithms with O(2ⁿ) exponential time complexity.
|
Package exponential contains implementations of algorithms with O(2ⁿ) exponential time complexity. |
|
factorial
Package factorial contains implementations of algorithms with O(n!) factorial time complexity.
|
Package factorial contains implementations of algorithms with O(n!) factorial time complexity. |
|
hyperexponential
Package hyperexponential contains implementations of algorithms with O(n^n) hyperexponential time complexity.
|
Package hyperexponential contains implementations of algorithms with O(n^n) hyperexponential time complexity. |
|
inverseackermann
Package inverseackermann contains implementations of algorithms with O(α(n)) inverse Ackermann time complexity.
|
Package inverseackermann contains implementations of algorithms with O(α(n)) inverse Ackermann time complexity. |
|
linear
Package linear contains implementations of algorithms with O(n) linear time complexity.
|
Package linear contains implementations of algorithms with O(n) linear time complexity. |
|
linearithmic
Package linearithmic contains implementations of algorithms with O(n log n) linearithmic time complexity.
|
Package linearithmic contains implementations of algorithms with O(n log n) linearithmic time complexity. |
|
logarithmic
Package logarithmic contains implementations of algorithms with O(log n) logarithmic time complexity.
|
Package logarithmic contains implementations of algorithms with O(log n) logarithmic time complexity. |
|
loglog
Package loglog contains implementations of algorithms with O(log log n) double logarithmic time complexity.
|
Package loglog contains implementations of algorithms with O(log log n) double logarithmic time complexity. |
|
nlogstar
Package nlogstar contains implementations of algorithms with O(n log*(n)) complexity, where log*(n) is the iterated logarithm.
|
Package nlogstar contains implementations of algorithms with O(n log*(n)) complexity, where log*(n) is the iterated logarithm. |
|
polylogarithmic
Package polylogarithmic contains implementations of algorithms with O((log n)^c) polylogarithmic time complexity.
|
Package polylogarithmic contains implementations of algorithms with O((log n)^c) polylogarithmic time complexity. |
|
polynomial
Package polynomial contains implementations of algorithms with polynomial time complexity O(nᵏ) where k > 3.
|
Package polynomial contains implementations of algorithms with polynomial time complexity O(nᵏ) where k > 3. |
|
quadratic
Package quadratic contains implementations of algorithms with O(n²) quadratic time complexity.
|
Package quadratic contains implementations of algorithms with O(n²) quadratic time complexity. |