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