func PseudoMetric(m markov.MarkovChain, lambda float64, TPSolver func(markov.MarkovChain, *coupling.Node, [][]float64, float64, int, int)) [][]float64 { // initialize all the sets and the coupling n := len(m.Transitions) tocompute := sets.InitToCompute(len(m.Transitions)) visited := sets.MakeMatrix(n) exact := sets.MakeMatrix(n) c := coupling.New() d := InitD(n) for !sets.EmptySet(tocompute) { var node *coupling.Node s, t := extractrandomfromset(tocompute) s, t = utils.GetMinMax(s, t) tocompute[s][t], tocompute[t][s] = false, false log.Printf("Run with node: (%v,%v)", s, t) if m.Labels[s] != m.Labels[t] { // s and t have the same label, so we set its distance to 0, and its exact and visited to true log.Printf("State %v and %v had different labels", s, t) d[s][t] = 1 exact[s][t] = true visited[s][t] = true continue } else if s == t { // s and t are the same state, so we set its distance to 1, and its exact and visited to true log.Printf("State %v %v) was the same state", s, t) d[s][t] = 0 exact[s][t] = true visited[s][t] = true continue } // since the pair of states is not the same and share a label, we have to further process it // try to find the correpsonding node in the coupling node = coupling.FindNode(s, t, &c) if node == nil { // if FindNode returned a nil pointer, the node does not exist, and we have to make it node = matching.FindFeasibleMatching(m, s, t, &c) setpair.Setpair(m, node, exact, visited, d, &c) } else if node.Adj == nil { // if FindNode did return a node reference, but its adjacency matrix(matching) is nil, we have to create it node = matching.FindFeasibleMatching(m, s, t, &c) setpair.Setpair(m, node, exact, visited, d, &c) } disc.Disc(lambda, node, exact, d, &c) updateUntilOptimalSolutionsFound(lambda, m, node, exact, visited, d, c, TPSolver, []*coupling.Node{}) removeExactEdges(node, exact) // remove everything that has been computed to exact, such that we will not try to solve it again tocompute = *sets.DifferensReal(&tocompute, &exact) } return d }
func filloutAdj(row, col []int, lenrow, lencol int, w [][]*coupling.Edge, c *coupling.Coupling) { for i := 0; i < lenrow; i++ { for j := 0; j < lencol; j++ { var node *coupling.Node s, t := utils.GetMinMax(row[i], col[j]) node = coupling.FindNode(s, t, c) if node == nil { node = &coupling.Node{S: s, T: t, Succ: []*coupling.Node{}} c.Nodes = append(c.Nodes, node) } w[i][j] = &coupling.Edge{To: node} } } }
func FindFeasibleMatching(m markov.MarkovChain, u int, v int, c *coupling.Coupling) *coupling.Node { n := len(m.Transitions[u]) u, v = utils.GetMinMax(u, v) // tries to find the node (u,v) in c, if not make a new one and add to c node := coupling.FindNode(u, v, c) if node == nil { node = &coupling.Node{S: u, T: v, Succ: []*coupling.Node{}} c.Nodes = append(c.Nodes, node) } log.Printf("copy the transitions from the states %v and %v", u, v) uTransitions := make([]float64, n, n) vTransitions := make([]float64, n, n) // copies the transitions of u and v such that we do not makes changes in the markov chain copy(uTransitions, m.Transitions[u]) copy(vTransitions, m.Transitions[v]) // finds the length of the rows and columns in the matching for u and v lenrow, lencol := matchingDimensions(uTransitions, vTransitions, n) log.Printf("row and column length are: %v and %v", lenrow, lencol) rowindex := make([]int, lenrow, lenrow) colindex := make([]int, lencol, lencol) // finds the row and column indexs for the u and v matching setMatchingIndexes(uTransitions, vTransitions, n, rowindex, colindex) log.Printf("row index: %s", rowindex) log.Printf("column index: %s", colindex) matching := make([][]*coupling.Edge, lenrow, lenrow) for i := range matching { matching[i] = make([]*coupling.Edge, lencol, lencol) } // fills out the matching with node pointers, using nodes already in the coupling c if they exist filloutAdj(rowindex, colindex, lenrow, lencol, matching, c) // completes the matching by inserting probabilities and setting appropriate cells to basic i, j := 0, 0 for i < lenrow && j < lencol { if utils.ApproxEqual(uTransitions[rowindex[i]], vTransitions[colindex[j]]) { matching[i][j].Prob = uTransitions[rowindex[i]] // check if we are in the lower right corner, such that we do not get an out of bounds error if !(i+1 == lenrow && j+1 == lencol) { matching[i][j+1].Basic = true node.BasicCount++ } matching[i][j].Basic = true matching[i][j].To.Succ = append(matching[i][j].To.Succ, node) node.BasicCount++ i++ j++ } else if uTransitions[rowindex[i]] < vTransitions[colindex[j]] { matching[i][j].Prob = uTransitions[rowindex[i]] vTransitions[colindex[j]] = vTransitions[colindex[j]] - uTransitions[rowindex[i]] matching[i][j].Basic = true matching[i][j].To.Succ = append(matching[i][j].To.Succ, node) node.BasicCount++ i++ } else { matching[i][j].Prob = vTransitions[colindex[j]] uTransitions[rowindex[i]] = uTransitions[rowindex[i]] - vTransitions[colindex[j]] matching[i][j].Basic = true matching[i][j].To.Succ = append(matching[i][j].To.Succ, node) node.BasicCount++ j++ } } log.Println("Logging matching:") for i := 0; i < lenrow; i++ { for j := 0; j < lencol; j++ { log.Printf(" - At: u %d, %d prob: %f, basic: %t", matching[i][j].To.S, matching[i][j].To.T, matching[i][j].Prob, matching[i][j].Basic) } } node.Adj = matching return node }