Beispiel #1
0
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
}
Beispiel #2
0
func TestSettingZeroDistanceAndExact(t *testing.T) {
	expected := [][]bool{
		[]bool{false, true, false, false, false, false, false},
		[]bool{false, true, true, false, false, false, false},
		[]bool{false, false, true, false, false, true, false},
		[]bool{false, false, false, false, false, false, false},
		[]bool{false, false, false, false, false, false, false},
		[]bool{false, false, false, false, false, false, false},
		[]bool{false, false, false, false, false, false, false}}

	c, m, visited, exact, d := coupling.SetUpTest()

	w := matching.FindFeasibleMatching(m, 0, 3, &c)
	setpair.Setpair(m, w, exact, visited, d, &c)

	nonz := findNonZero(w, exact, d, &c)

	setZerosDistanceToZero(w, nonz, exact, d, &c)

	for i := 0; i < len(expected); i++ {
		for j := 0; j < len(expected[0]); j++ {
			assert.Equal(t, expected[i][j], exact[i][j], "the cell (%v,%v) were not correcly set", i, j)
		}
	}

	assert.True(t, utils.ApproxEqual(d[0][1], 1), "the distance for node (0,1) was changed")
	assert.True(t, utils.ApproxEqual(d[2][2], 0), "the distance for node (1,1) was not set to 0")
}
Beispiel #3
0
func TestDisc(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)

	Disc(1.0, w, exact, d, &c)

	assert.True(t, utils.ApproxEqual(d[0][3], 0.9133), "the distance was not correctly set")
	assert.True(t, utils.ApproxEqual(d[2][3], 0.49), "the distance was not correctly set")
}
Beispiel #4
0
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")
}
Beispiel #5
0
func TestDiscResetsVisited(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)

	Disc(1, w, exact, d, &c)

	for _, node := range c.Nodes {
		assert.False(t, node.Visited, "visited for node (%v,%v) was true", node.S, node.T)
	}
}
Beispiel #6
0
func TestCorrectExactSet(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

	removeExactEdges(n, exact)

	assert.True(t, exact[n.S][n.T], "node (2,3) were not set to true in exact")
	assert.False(t, exact[w.S][w.T], "node (2,3) were not set to true in exact")
}
Beispiel #7
0
func TestCorrectEdgesRemoved(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

	removeExactEdges(n, exact)

	assert.True(t, n.Adj == nil, "the adjacency matrix for (2,3) was not set to nil")
	assert.True(t, w.Adj != nil, "the adjacency matrix for (2,3) was set to nil")
	assert.False(t, w.Visited, "the visited bool for node (0,3) was not changed back to false")
	assert.False(t, n.Visited, "the visited bool for node (2,3) was not changed back to false")
}
Beispiel #8
0
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")
}
Beispiel #9
0
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)")
}
Beispiel #10
0
func TestCorrectLinearFunctionsCreated(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)

	a, b, index := setUpLinearEquationFrame()

	setUpLinearEquations(w, exact, d, &a, &b, 0, &index, 1.0)

	checkEquationDimensions(t, a, b, index, 2)

	assert.True(t, utils.ApproxEqual(b[0], 0.83))
	assert.True(t, utils.ApproxEqual(b[1], 0.49))

	assert.Equal(t, 1.0, a[0][0], "the value in the matrix diagonal was not 1.0")
	assert.True(t, utils.ApproxEqual(a[0][1], -0.17), "the value in the matrix was not -0.17")
	assert.Equal(t, 0.0, a[1][0], "the value in the matrix was not 0.0")
	assert.Equal(t, 1.0, a[1][1], "the value in the matrix diagonal was not 1.0")
}
Beispiel #11
0
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
}
Beispiel #12
0
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)")
}
Beispiel #13
0
func TestOptimalSolutionFound(t *testing.T) {
	c, m, visited, exact, d := coupling.SetUpTest()
	d = sets.InitD(len(m.Transitions))

	w := matching.FindFeasibleMatching(m, 0, 3, &c)
	setpair.Setpair(m, w, exact, visited, d, &c)

	// the expected solution is not precice since the markov chain used do not use precise fractions
	expected := [][]float64{
		[]float64{0, 0.33, 0},
		[]float64{0, 0, 0.33},
		[]float64{0.17, 0, 0},
		[]float64{0.16, 0, 0.01}}

	min, i, j := uvmethod.Run(w, d)

	Solve(m, w, d, min, i, j)

	for i := range w.Adj {
		for j := range w.Adj[0] {
			assert.True(t, utils.ApproxEqual(expected[i][j], w.Adj[i][j].Prob), "the optimal probability found was not what we expected")
		}
	}
}
Beispiel #14
0
func TestCorrectLinearFunctionsCreatedLoops(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)

	a, b, index := setUpLinearEquationFrame()

	// inserting two loops into the coupling
	w.Adj[0][0] = &coupling.Edge{w, 0.33, true}
	w.Adj[2][2].To.Adj[1][2] = &coupling.Edge{w, 0.34, true}

	setUpLinearEquations(w, exact, d, &a, &b, 0, &index, 1.0)

	checkEquationDimensions(t, a, b, index, 2)

	assert.True(t, utils.ApproxEqual(b[0], 0.5))
	assert.True(t, utils.ApproxEqual(b[1], 0.49))

	assert.True(t, utils.ApproxEqual(a[0][0], 0.67), "the value in the matrix diagonal was not 0.67")
	assert.True(t, utils.ApproxEqual(a[0][1], -0.17), "the value in the matrix was not -0.17")
	assert.True(t, utils.ApproxEqual(a[1][0], -0.34), "the value in the matrix was not 0.0")
	assert.Equal(t, 1.0, a[1][1], "the value in the matrix diagonal was not 1.0")
}