| package bipartitegraph | 
 |  | 
 | import . "github.com/onsi/gomega/matchers/support/goraph/node" | 
 | import . "github.com/onsi/gomega/matchers/support/goraph/edge" | 
 | import "github.com/onsi/gomega/matchers/support/goraph/util" | 
 |  | 
 | func (bg *BipartiteGraph) LargestMatching() (matching EdgeSet) { | 
 | 	paths := bg.maximalDisjointSLAPCollection(matching) | 
 |  | 
 | 	for len(paths) > 0 { | 
 | 		for _, path := range paths { | 
 | 			matching = matching.SymmetricDifference(path) | 
 | 		} | 
 | 		paths = bg.maximalDisjointSLAPCollection(matching) | 
 | 	} | 
 |  | 
 | 	return | 
 | } | 
 |  | 
 | func (bg *BipartiteGraph) maximalDisjointSLAPCollection(matching EdgeSet) (result []EdgeSet) { | 
 | 	guideLayers := bg.createSLAPGuideLayers(matching) | 
 | 	if len(guideLayers) == 0 { | 
 | 		return | 
 | 	} | 
 |  | 
 | 	used := make(map[Node]bool) | 
 |  | 
 | 	for _, u := range guideLayers[len(guideLayers)-1] { | 
 | 		slap, found := bg.findDisjointSLAP(u, matching, guideLayers, used) | 
 | 		if found { | 
 | 			for _, edge := range slap { | 
 | 				used[edge.Node1] = true | 
 | 				used[edge.Node2] = true | 
 | 			} | 
 | 			result = append(result, slap) | 
 | 		} | 
 | 	} | 
 |  | 
 | 	return | 
 | } | 
 |  | 
 | func (bg *BipartiteGraph) findDisjointSLAP( | 
 | 	start Node, | 
 | 	matching EdgeSet, | 
 | 	guideLayers []NodeOrderedSet, | 
 | 	used map[Node]bool, | 
 | ) ([]Edge, bool) { | 
 | 	return bg.findDisjointSLAPHelper(start, EdgeSet{}, len(guideLayers)-1, matching, guideLayers, used) | 
 | } | 
 |  | 
 | func (bg *BipartiteGraph) findDisjointSLAPHelper( | 
 | 	currentNode Node, | 
 | 	currentSLAP EdgeSet, | 
 | 	currentLevel int, | 
 | 	matching EdgeSet, | 
 | 	guideLayers []NodeOrderedSet, | 
 | 	used map[Node]bool, | 
 | ) (EdgeSet, bool) { | 
 | 	used[currentNode] = true | 
 |  | 
 | 	if currentLevel == 0 { | 
 | 		return currentSLAP, true | 
 | 	} | 
 |  | 
 | 	for _, nextNode := range guideLayers[currentLevel-1] { | 
 | 		if used[nextNode] { | 
 | 			continue | 
 | 		} | 
 |  | 
 | 		edge, found := bg.Edges.FindByNodes(currentNode, nextNode) | 
 | 		if !found { | 
 | 			continue | 
 | 		} | 
 |  | 
 | 		if matching.Contains(edge) == util.Odd(currentLevel) { | 
 | 			continue | 
 | 		} | 
 |  | 
 | 		currentSLAP = append(currentSLAP, edge) | 
 | 		slap, found := bg.findDisjointSLAPHelper(nextNode, currentSLAP, currentLevel-1, matching, guideLayers, used) | 
 | 		if found { | 
 | 			return slap, true | 
 | 		} | 
 | 		currentSLAP = currentSLAP[:len(currentSLAP)-1] | 
 | 	} | 
 |  | 
 | 	used[currentNode] = false | 
 | 	return nil, false | 
 | } | 
 |  | 
 | func (bg *BipartiteGraph) createSLAPGuideLayers(matching EdgeSet) (guideLayers []NodeOrderedSet) { | 
 | 	used := make(map[Node]bool) | 
 | 	currentLayer := NodeOrderedSet{} | 
 |  | 
 | 	for _, node := range bg.Left { | 
 | 		if matching.Free(node) { | 
 | 			used[node] = true | 
 | 			currentLayer = append(currentLayer, node) | 
 | 		} | 
 | 	} | 
 |  | 
 | 	if len(currentLayer) == 0 { | 
 | 		return []NodeOrderedSet{} | 
 | 	} else { | 
 | 		guideLayers = append(guideLayers, currentLayer) | 
 | 	} | 
 |  | 
 | 	done := false | 
 |  | 
 | 	for !done { | 
 | 		lastLayer := currentLayer | 
 | 		currentLayer = NodeOrderedSet{} | 
 |  | 
 | 		if util.Odd(len(guideLayers)) { | 
 | 			for _, leftNode := range lastLayer { | 
 | 				for _, rightNode := range bg.Right { | 
 | 					if used[rightNode] { | 
 | 						continue | 
 | 					} | 
 |  | 
 | 					edge, found := bg.Edges.FindByNodes(leftNode, rightNode) | 
 | 					if !found || matching.Contains(edge) { | 
 | 						continue | 
 | 					} | 
 |  | 
 | 					currentLayer = append(currentLayer, rightNode) | 
 | 					used[rightNode] = true | 
 |  | 
 | 					if matching.Free(rightNode) { | 
 | 						done = true | 
 | 					} | 
 | 				} | 
 | 			} | 
 | 		} else { | 
 | 			for _, rightNode := range lastLayer { | 
 | 				for _, leftNode := range bg.Left { | 
 | 					if used[leftNode] { | 
 | 						continue | 
 | 					} | 
 |  | 
 | 					edge, found := bg.Edges.FindByNodes(leftNode, rightNode) | 
 | 					if !found || !matching.Contains(edge) { | 
 | 						continue | 
 | 					} | 
 |  | 
 | 					currentLayer = append(currentLayer, leftNode) | 
 | 					used[leftNode] = true | 
 | 				} | 
 | 			} | 
 |  | 
 | 		} | 
 |  | 
 | 		if len(currentLayer) == 0 { | 
 | 			return []NodeOrderedSet{} | 
 | 		} else { | 
 | 			guideLayers = append(guideLayers, currentLayer) | 
 | 		} | 
 | 	} | 
 |  | 
 | 	return | 
 | } |