Пример #1
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")
}
Пример #2
0
func TestGuassian(t *testing.T) {
	a := [][]float64{[]float64{1.0, -(1.0 / 6.0)}, []float64{0.0, 1.0}}
	b := []float64{5.0 / 6.0, 1.0 / 2.0}
	x, err := GaussPartial(a, b)

	assert.Equal(t, nil, err, "the linear equations was not calculate correctly")
	assert.True(t, utils.ApproxEqual(x[0], 11.0/12.0), "the found x value was not 11/12")
	assert.True(t, utils.ApproxEqual(x[1], 0.5), "the found x value was not 1/2")
}
Пример #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")
}
Пример #4
0
func TestGoVerticalReturnsTrue(t *testing.T) {
	c := setUpCoupling()
	min := 0.3

	n := c.Nodes[1]

	done := goVertical(n, 1, 0, 1, 1, 2, 2, 2, &min)

	assert.True(t, done, "goVertical did not compplete the stepping stone path")
	assert.True(t, utils.ApproxEqual(0.0, n.Adj[1][0].Prob), "the cell (1 0) were changed")
	assert.False(t, utils.ApproxEqual(0.3, n.Adj[1][1].Prob), "the cell (1 1) were not changed")
}
Пример #5
0
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
}
Пример #6
0
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++
		}
	}
}
Пример #7
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")
}
Пример #8
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")
}
Пример #9
0
func TestCorrectNestedMatchingFound(t *testing.T) {
	expected := [][]float64{
		[]float64{0.33, 0.17, 0.0},
		[]float64{0.0, 0.16, 0.34}}
	// 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

	for i := 0; i < len(expected); i++ {
		for j := 0; j < len(expected[0]); j++ {
			assert.True(t, utils.ApproxEqual(expected[i][j], node.Adj[i][j].Prob), "the correct probability for cell (%v,%v) were not inserted", i, j)
		}
	}
}
Пример #10
0
func findDemandedPairs(w *coupling.Node, visited [][]bool) []*coupling.Edge {
	demanded := make([]*coupling.Edge, 0)

	for _, rows := range w.Adj {
		for _, edge := range rows {
			if utils.ApproxEqual(edge.Prob, 0.0) {
				continue
			}
			if visited[edge.To.S][edge.To.T] || visited[edge.To.T][edge.To.S] {
				continue
			}

			demanded = append(demanded, edge)
		}
	}

	return demanded
}
Пример #11
0
func TestCorrectMatchingFound(t *testing.T) {
	expected := [][]float64{
		[]float64{0.33, 0.0, 0.0},
		[]float64{0.0, 0.33, 0.0},
		[]float64{0.0, 0.0, 0.17},
		[]float64{0.0, 0.0, 0.17}}

	c := coupling.New()
	m := coupling.SetUpMarkov()

	w := FindFeasibleMatching(m, 0, 3, &c)

	for i := 0; i < len(expected); i++ {
		for j := 0; j < len(expected[0]); j++ {
			assert.True(t, utils.ApproxEqual(expected[i][j], w.Adj[i][j].Prob), "the correct probability were not inserted")
		}
	}
}
Пример #12
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
}
Пример #13
0
func visit(root *Node, results []*Node) []*Node {
	// log.Printf("%s, %s", root.S, root.T)
	if root.Adj == nil {
		return results
	}

	for i := range root.Adj {
		for j := range root.Adj[0] {
			edge := root.Adj[i][j]
			toVisit := edge.To

			if !edge.Basic || toVisit.Visited {
				continue
			} else if !utils.ApproxEqual(edge.Prob, 0) {
				toVisit.Visited = true
				results = append(results, toVisit)
				results = visit(toVisit, results)
			}
		}
	}

	return results
}
Пример #14
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")
		}
	}
}
Пример #15
0
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
}