func TestCorrectSetSuccNodes(t *testing.T) { c := setUpCoupling() n2 := c.Nodes[1] SteppingStone(n2, 1, 0) assert.True(t, coupling.IsNodeInSlice(n2, c.Nodes[0].Succ), "node (1,0) did not remain a successor for (0,0)") assert.True(t, coupling.IsNodeInSlice(n2, c.Nodes[1].Succ), "node (1,0) did not remain a successor for (0,1)") assert.True(t, coupling.IsNodeInSlice(n2, c.Nodes[2].Succ), "node (1,0) did not become a successor for (1,0)") assert.False(t, coupling.IsNodeInSlice(n2, c.Nodes[3].Succ), "node (1,0) remained a successor for (1,1)") }
func TestCorrectFindNonZeros(t *testing.T) { c, m, visited, exact, d := coupling.SetUpTest() w := matching.FindFeasibleMatching(m, 0, 3, &c) setpair.Setpair(m, w, exact, visited, d, &c) nonZero := findNonZero(w, exact, d, &c) assert.Equal(t, len(nonZero), 5, "the length of the non-zero node slice was not 5") assert.True(t, coupling.IsNodeInSlice(w, nonZero), "node (0,3) was not added to the non-zero slice") assert.True(t, coupling.IsNodeInSlice(w.Adj[2][2].To, nonZero), "node (2,3) was not added to the non-zero slice") }
func TestCorrectFilterNonZero(t *testing.T) { c, m, visited, exact, d := coupling.SetUpTest() w := matching.FindFeasibleMatching(m, 0, 3, &c) setpair.Setpair(m, w, exact, visited, d, &c) reachables := coupling.Reachable(w) nonZeroReachables := filterZeros(reachables, exact, d) assert.Equal(t, len(nonZeroReachables), 3, "the filtered node slice did not have length 3") assert.False(t, coupling.IsNodeInSlice(w.Adj[2][2].To, nonZeroReachables), "node (2,3) was not filtered") assert.True(t, coupling.IsNodeInSlice(w.Adj[0][0].To, nonZeroReachables), "node (0,1) was filtered") assert.True(t, coupling.IsNodeInSlice(w.Adj[3][2].To, nonZeroReachables), "node (2,5) was filtered") assert.False(t, coupling.IsNodeInSlice(w.Adj[2][2].To.Adj[0][1].To, nonZeroReachables), "node (1,1) was not filtered") }
func TestCorrectSuccNodesRemoved(t *testing.T) { c, m, visited, exact, d := coupling.SetUpTest() w := matching.FindFeasibleMatching(m, 0, 3, &c) setpair.Setpair(m, w, exact, visited, d, &c) n := w.Adj[2][2].To n2 := n.Adj[1][2].To removeExactEdges(n, exact) assert.True(t, coupling.IsNodeInSlice(w, n.Succ), "node (0,3) was removed as a successor for (2,3)") assert.False(t, coupling.IsNodeInSlice(n, w.Adj[0][0].To.Succ), "node (2,3) is still a successor for (0,1)") assert.True(t, coupling.IsNodeInSlice(w, w.Adj[0][0].To.Succ), "node (0,3) was removed as a successor for (0,1)") assert.False(t, coupling.IsNodeInSlice(n, n2.Succ), "node (2,3) was not removed as a successor for (2,2)") }
func updateEdge(edge *coupling.Edge, signal bool, min float64, n *coupling.Node) { if signal { log.Printf("increasing at cell (%v,%v)", edge.To.S, edge.To.T) // increase and set the node to basic edge.Prob += min if !edge.Basic { edge.Basic = true n.BasicCount++ } // add the main node as a successor to the node if it not already is if !coupling.IsNodeInSlice(n, edge.To.Succ) { edge.To.Succ = append(edge.To.Succ, n) } } else { log.Printf("decreasing at cell (%v,%v)", edge.To.S, edge.To.T) edge.Prob -= min // if the line edge.Prob -= min, makes edge.Prob to zero, it is not a basic cell edge.Basic = !utils.ApproxEqual(edge.Prob, 0) // if no longer basic remove the main node as a successor for the node if !edge.Basic { coupling.DeleteNodeInSlice(n, &edge.To.Succ) n.BasicCount-- } } edge.To.Visited = false }
func updateNode(node *coupling.Node, newValues []float64) { if (len(node.Adj) * len(node.Adj[0])) != len(newValues) { log.Printf("%v %v", (len(node.Adj) * len(node.Adj[0])), len(newValues)) panic("The amount of new values does not match the adjacency matrix!") } k := 0 for i := range (*node).Adj { for _, edge := range (*node).Adj[i] { prevBasic := edge.Basic prob := newValues[k] if utils.ApproxEqual(prob, 0.0) { edge.Basic = false coupling.DeleteNodeInSlice(node, &edge.To.Succ) if prevBasic { node.BasicCount-- } } else { edge.Basic = true if !prevBasic { node.BasicCount++ } if !coupling.IsNodeInSlice(node, edge.To.Succ) { edge.To.Succ = append(edge.To.Succ, node) } } edge.Prob = prob k++ } } }
func TestCorrectSuccessorFound(t *testing.T) { c := coupling.New() m := coupling.SetUpMarkov() w := FindFeasibleMatching(m, 0, 3, &c) log.Println(w.Adj[2][2].To) assert.True(t, coupling.IsNodeInSlice(w, w.Adj[0][0].To.Succ), "node (0,3) did not become a successor for (0,1)") assert.True(t, coupling.IsNodeInSlice(w, w.Adj[1][1].To.Succ), "node (0,3) did not become a successor for (1,2)") assert.True(t, coupling.IsNodeInSlice(w, w.Adj[2][2].To.Succ), "node (0,3) did not become a successor for (2,3)") assert.True(t, coupling.IsNodeInSlice(w, w.Adj[3][2].To.Succ), "node (0,3) did not become a successor for (2,5)") assert.False(t, coupling.IsNodeInSlice(w, w.Adj[0][1].To.Succ), "node (0,3) become a successor for (1,1)") assert.False(t, coupling.IsNodeInSlice(w, w.Adj[1][0].To.Succ), "node (0,3) become a successor for (0,2)") }
func findReverseReachable(node *coupling.Node, reachables []*coupling.Node) []*coupling.Node { node.Visited = true for _, succ := range node.Succ { if !coupling.IsNodeInSlice(succ, reachables) { reachables = append(reachables, succ) } if len(succ.Succ) == 0 || succ.Visited { continue } reachables = findReverseReachable(succ, reachables) } node.Visited = false return reachables }
func updateUntilOptimalSolutionsFound(lambda float64, m markov.MarkovChain, node *coupling.Node, exact [][]bool, visited [][]bool, d [][]float64, c coupling.Coupling, TPSolver func(markov.MarkovChain, *coupling.Node, [][]float64, float64, int, int), solvedNodes []*coupling.Node) { log.Printf("find optimal for: (%v,%v)", node.S, node.T) min, i, j := uvmethod.Run(node, d) // if min is negative, we can further improve it, so we update it using the TPSolver and iterated until we cannot improve it further for min < 0 && !utils.ApproxEqual(min, 0) { previ, prevj := i, j TPSolver(m, node, d, min, i, j) setpair.Setpair(m, node, exact, visited, d, &c) disc.Disc(lambda, node, exact, d, &c) min, i, j = uvmethod.Run(node, d) if previ == i && prevj == j && min < 0 { break } } // append solved nodes such that we do not end up recurively calling nodes that have already been found to be optimal solvedNodes = append(solvedNodes, node) for _, row := range node.Adj { for _, edge := range row { if edge.To.Adj == nil { // if the node do not have an adjacency matrix or is exact, we do not have to proccess it continue } if coupling.IsNodeInSlice(edge.To, solvedNodes) { // if the node has already been proccesses, we do not have to do it again continue } updateUntilOptimalSolutionsFound(lambda, m, edge.To, exact, visited, d, c, TPSolver, solvedNodes) } } exact[node.S][node.T] = true exact[node.S][node.T] = true return }
func TestCorrectNestedSuccessorFound(t *testing.T) { // the same functions used for random matching testing c, m, visited, exact, d := coupling.SetUpTest() w := matching.FindFeasibleMatching(m, 0, 3, &c) Setpair(m, w, exact, visited, d, &c) node := w.Adj[2][2].To assert.True(t, coupling.IsNodeInSlice(node, node.Adj[0][0].To.Succ), "node (2,3) did not become a successor for (0,1)") assert.True(t, coupling.IsNodeInSlice(node, node.Adj[0][1].To.Succ), "node (2,3) did not become a successor for (1,1)") assert.True(t, coupling.IsNodeInSlice(node, node.Adj[1][1].To.Succ), "node (2,3) did not become a successor for (1,2)") assert.True(t, coupling.IsNodeInSlice(node, node.Adj[1][2].To.Succ), "node (2,3) did not become a successor for (2,2)") // common children between node(2,3) and w(0,3) assert.True(t, coupling.IsNodeInSlice(w, node.Adj[0][0].To.Succ), "node (0,1) did not have node (0,3) as a successor") assert.True(t, coupling.IsNodeInSlice(w, node.Adj[1][1].To.Succ), "node (1,2) did not have node (0,3) as a successor") }
func TestCorrectReverseCouplingNodesFound(t *testing.T) { c, m, visited, exact, d := coupling.SetUpTest() w := matching.FindFeasibleMatching(m, 0, 3, &c) setpair.Setpair(m, w, exact, visited, d, &c) nonZeroReachables := []*coupling.Node{} nonZeroReachables = findReverseReachable(w.Adj[0][0].To, nonZeroReachables) assert.True(t, coupling.IsNodeInSlice(w, nonZeroReachables), "node (0,3) was not a successor for (0,1)") assert.True(t, coupling.IsNodeInSlice(w.Adj[2][2].To, nonZeroReachables), "node (2,3) was not a successor for (0,1)") assert.False(t, coupling.IsNodeInSlice(w.Adj[1][1].To, nonZeroReachables), "node (1,2) was a successor for (0,1)") assert.False(t, coupling.IsNodeInSlice(w.Adj[2][2].To.Adj[1][2].To, nonZeroReachables), "node (2,2) was a successor for (0,1)") nonZeroReachables2 := []*coupling.Node{} nonZeroReachables2 = findReverseReachable(w.Adj[2][2].To, nonZeroReachables2) assert.True(t, coupling.IsNodeInSlice(w, nonZeroReachables2), "node (0,3) was not a successor for (2,3)") assert.False(t, coupling.IsNodeInSlice(w.Adj[0][0].To, nonZeroReachables2), "node (0,1) was a successor for (2,3)") }