Example #1
0
        /// <summary>
        /// Merges the node x into the fixed target node into.
        ///
        /// Edges between these nodes, edges to x and related distance information is updated.
        ///
        /// x is marked as to be removed from the search space. If x was the start node, into
        /// will now be the start node.
        /// </summary>
        /// <returns>All neighbors of x before merging. These are the nodes that had their adjacency
        /// information changed.</returns>
        protected IEnumerable <int> MergeInto(int x, int into)
        {
            if (!NodeStates.IsFixedTarget(into))
            {
                throw new ArgumentException("Nodes can only be merged into fixed target nodes", "into");
            }

            _data.DistanceLookup.IndexToNode(into).MergeWith(_data.DistanceLookup.IndexToNode(x), _data.DistanceLookup.GetShortestPath(x, into));
            _data.DistanceLookup.MergeInto(x, into);

            EdgeSet.Remove(x, into);
            var intoNeighbors = EdgeSet.NeighborsOf(into);
            var xNeighbors    = EdgeSet.NeighborsOf(x);
            var neighbors     = intoNeighbors.Union(xNeighbors);

            foreach (var neighbor in xNeighbors)
            {
                EdgeSet.Remove(x, neighbor);
            }
            foreach (var neighbor in neighbors)
            {
                EdgeSet.Add(into, neighbor, _data.DistanceLookup[into, neighbor]);
            }

            if (StartNodeIndex == x)
            {
                _data.StartNodeIndex = into;
            }

            NodeStates.MarkNodeAsRemoved(x);

            return(xNeighbors);
        }
        public override bool DeleteEdge(T v1, T v2)
        {
            if (v1 is null)
            {
                throw new ArgumentNullException(nameof(v1));
            }

            if (v2 is null)
            {
                throw new ArgumentNullException(nameof(v2));
            }

            IPairValue <T> pair_1 = new PairValueI <T>(v1, v2);
            IPairValue <T> pair_2 = new PairValueI <T>(v2, v1);

            if (EdgeSet.Contains(pair_1) || EdgeSet.Contains(pair_2))
            {
                EdgeSet.Remove(pair_1);
                Weights.Remove(pair_1);

                EdgeSet.Remove(pair_2);
                Weights.Remove(pair_2);
                return(true);
            }
            return(false);
        }
Example #3
0
        public override bool DeleteEdge(TV v1, TV v2)
        {
            if (v1 == null || v2 == null)
            {
                throw new ArgumentNullException();
            }
            IPairValue <TV> pair = new PairValue <TV>(v1, v2);

            if (EdgeSet.Contains(pair))
            {
                EdgeSet.Remove(pair);
                Weigths.Remove(pair);
                return(true);
            }
            return(false);
        }
Example #4
0
        public override bool DeleteEdge(T v1Key, T v2Key)
        {
            if (v1Key == null || v2Key == null)
            {
                throw new ArgumentNullException();
            }

            IPairValue <T> pair = new PairValue <T>(v1Key, v2Key);

            if (EdgeSet.Contains(pair))
            {
                EdgeSet.Remove(pair);
                Weights.Remove(pair);
                return(true);
            }

            return(false);
        }
Example #5
0
        private void RemoveNode(int index)
        {
            if (NodeStates.IsTarget(index))
            {
                throw new ArgumentException("Target nodes can't be removed", "index");
            }

            var neighbors = EdgeSet.NeighborsOf(index);

            switch (neighbors.Count)
            {
            case 0:
                break;

            case 1:
                EdgeSet.Remove(index, neighbors[0]);
                break;

            case 2:
                // Merge the two incident edges.
                var left      = neighbors[0];
                var right     = neighbors[1];
                var newWeight = EdgeSet[index, left].Weight + EdgeSet[index, right].Weight;
                EdgeSet.Remove(index, left);
                EdgeSet.Remove(index, right);
                if (newWeight <= DistanceLookup[left, right])
                {
                    EdgeSet.Add(left, right, newWeight);
                }
                break;

            default:
                throw new ArgumentException("Removing nodes with more than 2 neighbors is not supported", "index");
            }

            NodeStates.MarkNodeAsRemoved(index);
        }
        protected override int ExecuteTest()
        {
            var edges        = new GraphEdge[SearchSpaceSize];
            var removedNodes = 0;

            for (var i = 0; i < SearchSpaceSize; i++)
            {
                // This test only checks non-terminals.
                if (NodeStates.IsTarget(i))
                {
                    continue;
                }

                // Nodes with less than 3 neighbors are covered by DegreeTest
                // Nodes are limited to 7 neighbors because this test is exponential in the neighbor count.
                var neighbors = EdgeSet.NeighborsOf(i);
                if (neighbors.Count < 3 || neighbors.Count > 7)
                {
                    continue;
                }

                // Cache the edges. They might be removed from EdgeSet when we need them.
                foreach (var neighbor in neighbors)
                {
                    edges[neighbor] = EdgeSet[i, neighbor];
                }

                // Check whether each subset satisfies the condition.
                var canBeRemoved = true;
                foreach (var subset in GetAllSubsets(neighbors))
                {
                    // Only subsets of at least size 3 are relevant.
                    if (subset.Count < 3)
                    {
                        continue;
                    }

                    // Sum up the weights of all edges between the nodes of the subsets and i.
                    var edgeSum = subset.Sum(j => edges[j].Weight);
                    // Build the MST of the fully connected graph of the nodes in the subset with the bottleneck
                    // Steiner distances as edge weights.
                    var mst = new MinimalSpanningTree(subset, SMatrix);
                    mst.Span(subset[0]);
                    // Sum up the edge weights of the MST.
                    var mstSum = mst.SpanningEdges.Sum(e => e.Priority);
                    // The condition is only satisfied if edgeSum >= mstSum.
                    if (edgeSum < mstSum)
                    {
                        canBeRemoved = false;
                        break;
                    }
                }

                if (!canBeRemoved)
                {
                    continue;
                }

                // Remove i and replace its edges.
                foreach (var neighbor in neighbors)
                {
                    // Remove the old edges between i and its neighbors.
                    var edge = edges[neighbor];
                    EdgeSet.Remove(edge);
                    // For each pair of neighbors create a new edge.
                    foreach (var neighbor2 in neighbors)
                    {
                        if (neighbor >= neighbor2)
                        {
                            continue;
                        }
                        // The weight of the new edge between the two neighbors is the sum of their edge weights to i.
                        var edge2         = edges[neighbor2];
                        var newEdgeWeight = edge.Weight + edge2.Weight;
                        // Only add this edge if it wouldn't be removed by the Paths with many terminals test.
                        if (newEdgeWeight <= SMatrix[neighbor, neighbor2])
                        {
                            EdgeSet.Add(neighbor, neighbor2, newEdgeWeight);
                        }
                    }
                }

                NodeStates.MarkNodeAsRemoved(i);
                removedNodes++;
            }
            return(removedNodes);
        }