Simplify slack handling in delta2 tracking
This commit is contained in:
		
							parent
							
								
									9ee26584ab
								
							
						
					
					
						commit
						3a77749425
					
				| 
						 | 
				
			
			@ -613,7 +613,24 @@ class _MatchingContext:
 | 
			
		|||
            blossom.vertex_set.clear()
 | 
			
		||||
            del blossom.vertex_set
 | 
			
		||||
 | 
			
		||||
    def edge_slack_2x_info(
 | 
			
		||||
    def edge_pseudo_slack_2x(self, e: int) -> float:
 | 
			
		||||
        """Return 2 times the pseudo-slack of the specified edge.
 | 
			
		||||
 | 
			
		||||
        The pseudo-slack of an edge ignores pending changes to vertex duals.
 | 
			
		||||
 | 
			
		||||
        For an edge between two S-vertices (in different top-level blossoms),
 | 
			
		||||
        the true slack is the pseudo-slack minus 2 times the running sum
 | 
			
		||||
        of delta steps.
 | 
			
		||||
 | 
			
		||||
        For an edge between an S-vertex and unlabeled vertex,
 | 
			
		||||
        the true slack is the pseudo-slack minus the running sum of delta
 | 
			
		||||
        steps, plus the pending offset of the top-level blossom that contains
 | 
			
		||||
        the unlabeled vertex.
 | 
			
		||||
        """
 | 
			
		||||
        (x, y, w) = self.graph.edges[e]
 | 
			
		||||
        return self.vertex_dual_2x[x] + self.vertex_dual_2x[y] - 2 * w
 | 
			
		||||
 | 
			
		||||
    def edge_slack_2x(
 | 
			
		||||
            self,
 | 
			
		||||
            x: int,
 | 
			
		||||
            y: int,
 | 
			
		||||
| 
						 | 
				
			
			@ -645,13 +662,6 @@ class _MatchingContext:
 | 
			
		|||
        dual_2x += by.vertex_dual_offset
 | 
			
		||||
        return dual_2x - 2 * w
 | 
			
		||||
 | 
			
		||||
    def edge_slack_2x(self, e: int) -> float:
 | 
			
		||||
        """Return 2 times the slack of the edge with index "e"."""
 | 
			
		||||
        (x, y, w) = self.graph.edges[e]
 | 
			
		||||
        bx = self.vertex_set_node[x].find()
 | 
			
		||||
        by = self.vertex_set_node[y].find()
 | 
			
		||||
        return self.edge_slack_2x_info(x, y, bx, by, w)
 | 
			
		||||
 | 
			
		||||
    #
 | 
			
		||||
    # Least-slack edge tracking:
 | 
			
		||||
    #
 | 
			
		||||
| 
						 | 
				
			
			@ -689,36 +699,26 @@ class _MatchingContext:
 | 
			
		|||
        for blossom in self.trivial_blossom + self.nontrivial_blossom:
 | 
			
		||||
            blossom.delta2_node = None
 | 
			
		||||
 | 
			
		||||
    def lset_add_vertex_edge(
 | 
			
		||||
            self,
 | 
			
		||||
            y: int,
 | 
			
		||||
            by: _Blossom,
 | 
			
		||||
            e: int,
 | 
			
		||||
            slack: float
 | 
			
		||||
            ) -> None:
 | 
			
		||||
    def lset_add_vertex_edge(self, y: int, by: _Blossom, e: int) -> None:
 | 
			
		||||
        """Add edge "e" from an S-vertex to unlabeled vertex or T-vertex "y".
 | 
			
		||||
 | 
			
		||||
        This function takes time O(log(n)).
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        # TODO -- Simplify: We don't need to know the true slack of the edge,
 | 
			
		||||
        #            only the pseudo-slack based on raw vertex duals and weight.
 | 
			
		||||
        prio = self.edge_pseudo_slack_2x(e)
 | 
			
		||||
 | 
			
		||||
        best_edge = self.vertex_best_edge[y]
 | 
			
		||||
        if best_edge != -1:
 | 
			
		||||
            best_slack = self.edge_slack_2x(best_edge)
 | 
			
		||||
            if slack >= best_slack:
 | 
			
		||||
            best_prio = self.edge_pseudo_slack_2x(best_edge)
 | 
			
		||||
            if prio >= best_prio:
 | 
			
		||||
                return
 | 
			
		||||
 | 
			
		||||
        self.vertex_best_edge[y] = e
 | 
			
		||||
 | 
			
		||||
        (p, q, w) = self.graph.edges[e]
 | 
			
		||||
        prio = self.vertex_dual_2x[p] + self.vertex_dual_2x[q] - 2 * w
 | 
			
		||||
        prev_min = by.vertex_set.min_prio()
 | 
			
		||||
        self.vertex_set_node[y].set_prio(prio)
 | 
			
		||||
 | 
			
		||||
        if (by.label == _LABEL_NONE) and (prio < prev_min):
 | 
			
		||||
            prio = slack + self.delta_sum_2x
 | 
			
		||||
            prio += by.vertex_dual_offset
 | 
			
		||||
            if by.delta2_node is None:
 | 
			
		||||
                by.delta2_node = self.delta2_queue.insert(prio, by)
 | 
			
		||||
            elif prio < by.delta2_node.prio:
 | 
			
		||||
| 
						 | 
				
			
			@ -1476,7 +1476,7 @@ class _MatchingContext:
 | 
			
		|||
 | 
			
		||||
                # Check whether this edge is tight (has zero slack).
 | 
			
		||||
                # Only tight edges may be part of an alternating tree.
 | 
			
		||||
                slack = self.edge_slack_2x_info(x, y, bx, by, w)
 | 
			
		||||
                slack = self.edge_slack_2x(x, y, bx, by, w)
 | 
			
		||||
                if slack <= 0:
 | 
			
		||||
                    if ylabel == _LABEL_NONE:
 | 
			
		||||
                        # Assign label T to the blossom that contains "y".
 | 
			
		||||
| 
						 | 
				
			
			@ -1509,7 +1509,7 @@ class _MatchingContext:
 | 
			
		|||
                    # any S-vertex. We do this for T-vertices and unlabeled
 | 
			
		||||
                    # vertices. Edges which already have zero slack are still
 | 
			
		||||
                    # tracked.
 | 
			
		||||
                    self.lset_add_vertex_edge(y, by, e, slack)
 | 
			
		||||
                    self.lset_add_vertex_edge(y, by, e)
 | 
			
		||||
 | 
			
		||||
        # No further S vertices to scan, and no augmenting path found.
 | 
			
		||||
        return None
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue