github.com/Finschia/finschia-sdk@v0.48.1/x/simulation/transition_matrix.go (about) 1 package simulation 2 3 import ( 4 "fmt" 5 "math/rand" 6 7 "github.com/Finschia/finschia-sdk/types/simulation" 8 ) 9 10 // TransitionMatrix is _almost_ a left stochastic matrix. It is technically 11 // not one due to not normalizing the column values. In the future, if we want 12 // to find the steady state distribution, it will be quite easy to normalize 13 // these values to get a stochastic matrix. Floats aren't currently used as 14 // the default due to non-determinism across architectures 15 type TransitionMatrix struct { 16 weights [][]int 17 // total in each column 18 totals []int 19 n int 20 } 21 22 // CreateTransitionMatrix creates a transition matrix from the provided weights. 23 // TODO: Provide example usage 24 func CreateTransitionMatrix(weights [][]int) (simulation.TransitionMatrix, error) { 25 n := len(weights) 26 for i := 0; i < n; i++ { 27 if len(weights[i]) != n { 28 return TransitionMatrix{}, 29 fmt.Errorf("transition matrix: non-square matrix provided, error on row %d", i) 30 } 31 } 32 33 totals := make([]int, n) 34 35 for row := 0; row < n; row++ { 36 for col := 0; col < n; col++ { 37 totals[col] += weights[row][col] 38 } 39 } 40 41 return TransitionMatrix{weights, totals, n}, nil 42 } 43 44 // NextState returns the next state randomly chosen using r, and the weightings 45 // provided in the transition matrix. 46 func (t TransitionMatrix) NextState(r *rand.Rand, i int) int { 47 randNum := r.Intn(t.totals[i]) 48 for row := 0; row < t.n; row++ { 49 if randNum < t.weights[row][i] { 50 return row 51 } 52 53 randNum -= t.weights[row][i] 54 } 55 // This line should never get executed 56 return -1 57 } 58 59 // GetMemberOfInitialState takes an initial array of weights, of size n. 60 // It returns a weighted random number in [0,n). 61 func GetMemberOfInitialState(r *rand.Rand, weights []int) int { 62 n := len(weights) 63 total := 0 64 65 for i := 0; i < n; i++ { 66 total += weights[i] 67 } 68 69 randNum := r.Intn(total) 70 71 for state := 0; state < n; state++ { 72 if randNum < weights[state] { 73 return state 74 } 75 76 randNum -= weights[state] 77 } 78 // This line should never get executed 79 return -1 80 }