Beispiel #1
0
        /// <summary>
        /// Adds all downward edges.
        /// </summary>
        /// <param name="graph"></param>
        public static void AddDownwardEdges(this IDynamicGraph <CHEdgeData> graph)
        { // add the reverse edges to get a easy depth-first search.
            for (uint vertexId = 1; vertexId < graph.VertexCount; vertexId++)
            {
                List <KeyValuePair <uint, CHEdgeData> > arcs =
                    new List <KeyValuePair <uint, CHEdgeData> >(graph.GetArcs(vertexId));
                foreach (KeyValuePair <uint, CHEdgeData> arc in arcs)
                {
                    if (arc.Value.ToHigher)
                    {
                        // create severse edge.
                        CHEdgeData reverseEdge = new CHEdgeData();
                        reverseEdge.SetDirection(arc.Value.Backward, arc.Value.Forward, false);
                        reverseEdge.Weight = arc.Value.Weight;

                        graph.AddArc(arc.Key, vertexId, reverseEdge, null);
                    }
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Contracts the given vertex.
        /// </summary>
        /// <param name="vertex"></param>
        public void Contract(uint vertex)
        {
            if (_contracted.Length > vertex && _contracted[vertex])
            {
                throw new Exception("Is already contracted!");
            }

            // keep the neighbours.
            HashSet<KeyValuePair<uint, CHEdgeData>> neighbours =
                new HashSet<KeyValuePair<uint, CHEdgeData>>();

            // get all information from the source.
            KeyValuePair<uint, CHEdgeData>[] edges = _target.GetArcs(vertex);

            // remove all informative edges.
            edges = edges.RemoveInformativeEdges();

            // report the before contraction event.
            this.OnBeforeContraction(vertex, edges);

            // remove the edges from the neighbours to the target.
            foreach (KeyValuePair<uint, CHEdgeData> edge in edges)
            { // remove the edge.
                _target.DeleteArc(edge.Key, vertex);

                // keep the neighbour.
                if (_keepDirectNeighbours && !edge.Value.HasContractedVertex)
                { // edge does represent a neighbour relation.
                    neighbours.Add(
                        new KeyValuePair<uint, CHEdgeData>(edge.Key, edge.Value.ConvertToInformative()));
                }
            }

            // loop over each combination of edges just once.
            for (int x = 1; x < edges.Length; x++)
            { // loop over all elements first.
                KeyValuePair<uint, CHEdgeData> xEdge = edges[x];
                if (xEdge.Value.IsInformative) { continue; }

                for (int y = 0; y < x; y++)
                { // loop over all elements.
                    KeyValuePair<uint, CHEdgeData> yEdge = edges[y];
                    if (yEdge.Value.IsInformative) { continue; }

                    // calculate the total weight.
                    float weight = xEdge.Value.Weight + yEdge.Value.Weight;

                    // add the combinations of these edges.
                    if (((xEdge.Value.Backward && yEdge.Value.Forward) ||
                        (yEdge.Value.Backward && xEdge.Value.Forward)) &&
                        (xEdge.Key != yEdge.Key))
                    { // there is a connection from x to y and there is no witness path.
                        bool witnessXToY = _witnessCalculator.Exists(_target, xEdge.Key,
                            yEdge.Key, vertex, weight, 100);
                        bool witnessYToX = _witnessCalculator.Exists(_target, yEdge.Key,
                            xEdge.Key, vertex, weight, 100);

                        // create x-to-y data and edge.
                        CHEdgeData dataXToY = new CHEdgeData();
                        bool forward = (xEdge.Value.Backward && yEdge.Value.Forward) &&
                            !witnessXToY;
                        bool backward = (yEdge.Value.Backward && xEdge.Value.Forward) &&
                            !witnessYToX;
                        dataXToY.SetDirection(forward, backward, true);
                        dataXToY.Weight = weight;
                        dataXToY.ContractedVertexId = vertex;
                        if ((dataXToY.Forward || dataXToY.Backward) ||
                            !_target.HasArc(xEdge.Key, yEdge.Key))
                        { // add the edge if there is usefull info or if there needs to be a neighbour relationship.
                            _target.AddArc(xEdge.Key, yEdge.Key, dataXToY, _comparer);
                        }

                        // create y-to-x data and edge.
                        CHEdgeData dataYToX = new CHEdgeData();
                        forward = (yEdge.Value.Backward && xEdge.Value.Forward) &&
                            !witnessYToX;
                        backward = (xEdge.Value.Backward && yEdge.Value.Forward) &&
                            !witnessXToY;
                        dataYToX.SetDirection(forward, backward, true);
                        dataYToX.Weight = weight;
                        dataYToX.ContractedVertexId = vertex;
                        if ((dataYToX.Forward || dataYToX.Backward) ||
                            !_target.HasArc(yEdge.Key, xEdge.Key))
                        { // add the edge if there is usefull info or if there needs to be a neighbour relationship.
                            _target.AddArc(yEdge.Key, xEdge.Key, dataYToX, _comparer);
                        }
                    }
                }
            }

            // mark the vertex as contracted.
            this.MarkContracted(vertex);

            // notify a contracted neighbour.
            _calculator.NotifyContracted(vertex);

            // add contracted neighbour edges again.
            if (_keepDirectNeighbours)
            {
                foreach (KeyValuePair<uint, CHEdgeData> neighbour in neighbours)
                {
                    _target.AddArc(neighbour.Key, vertex, neighbour.Value, null);
                }
            }

            // report the after contraction event.
            this.OnAfterContraction(vertex, edges);
        }
Beispiel #3
0
        /// <summary>
        /// Contracts the given vertex.
        /// </summary>
        /// <param name="vertex"></param>
        public void Contract(uint vertex)
        {
            if (_contracted.Length > vertex && _contracted[vertex])
            {
                throw new Exception("Is already contracted!");
            }

            // keep the neighbours.
            HashSet <KeyValuePair <uint, CHEdgeData> > neighbours =
                new HashSet <KeyValuePair <uint, CHEdgeData> >();

            // get all information from the source.
            KeyValuePair <uint, CHEdgeData>[] edges = _target.GetArcs(vertex);

            // remove all informative edges.
            edges = edges.RemoveInformativeEdges();

            // report the before contraction event.
            this.OnBeforeContraction(vertex, edges);

            // remove the edges from the neighbours to the target.
            foreach (KeyValuePair <uint, CHEdgeData> edge in edges)
            { // remove the edge.
                _target.DeleteArc(edge.Key, vertex);

                // keep the neighbour.
                if (_keepDirectNeighbours && !edge.Value.HasContractedVertex)
                { // edge does represent a neighbour relation.
                    neighbours.Add(
                        new KeyValuePair <uint, CHEdgeData>(edge.Key, edge.Value.ConvertToInformative()));
                }
            }

            // loop over each combination of edges just once.
            for (int x = 1; x < edges.Length; x++)
            { // loop over all elements first.
                KeyValuePair <uint, CHEdgeData> xEdge = edges[x];
                if (xEdge.Value.IsInformative)
                {
                    continue;
                }

                for (int y = 0; y < x; y++)
                { // loop over all elements.
                    KeyValuePair <uint, CHEdgeData> yEdge = edges[y];
                    if (yEdge.Value.IsInformative)
                    {
                        continue;
                    }

                    // calculate the total weight.
                    float weight = xEdge.Value.Weight + yEdge.Value.Weight;

                    // add the combinations of these edges.
                    if (((xEdge.Value.Backward && yEdge.Value.Forward) ||
                         (yEdge.Value.Backward && xEdge.Value.Forward)) &&
                        (xEdge.Key != yEdge.Key))
                    { // there is a connection from x to y and there is no witness path.
                        bool witnessXToY = _witnessCalculator.Exists(_target, xEdge.Key,
                                                                     yEdge.Key, vertex, weight, 100);
                        bool witnessYToX = _witnessCalculator.Exists(_target, yEdge.Key,
                                                                     xEdge.Key, vertex, weight, 100);

                        // create x-to-y data and edge.
                        CHEdgeData dataXToY = new CHEdgeData();
                        bool       forward  = (xEdge.Value.Backward && yEdge.Value.Forward) &&
                                              !witnessXToY;
                        bool backward = (yEdge.Value.Backward && xEdge.Value.Forward) &&
                                        !witnessYToX;
                        dataXToY.SetDirection(forward, backward, true);
                        dataXToY.Weight             = weight;
                        dataXToY.ContractedVertexId = vertex;
                        if ((dataXToY.Forward || dataXToY.Backward) ||
                            !_target.HasArc(xEdge.Key, yEdge.Key))
                        { // add the edge if there is usefull info or if there needs to be a neighbour relationship.
                            _target.AddArc(xEdge.Key, yEdge.Key, dataXToY, _comparer);
                        }

                        // create y-to-x data and edge.
                        CHEdgeData dataYToX = new CHEdgeData();
                        forward = (yEdge.Value.Backward && xEdge.Value.Forward) &&
                                  !witnessYToX;
                        backward = (xEdge.Value.Backward && yEdge.Value.Forward) &&
                                   !witnessXToY;
                        dataYToX.SetDirection(forward, backward, true);
                        dataYToX.Weight             = weight;
                        dataYToX.ContractedVertexId = vertex;
                        if ((dataYToX.Forward || dataYToX.Backward) ||
                            !_target.HasArc(yEdge.Key, xEdge.Key))
                        { // add the edge if there is usefull info or if there needs to be a neighbour relationship.
                            _target.AddArc(yEdge.Key, xEdge.Key, dataYToX, _comparer);
                        }
                    }
                }
            }

            // mark the vertex as contracted.
            this.MarkContracted(vertex);

            // notify a contracted neighbour.
            _calculator.NotifyContracted(vertex);

            // add contracted neighbour edges again.
            if (_keepDirectNeighbours)
            {
                foreach (KeyValuePair <uint, CHEdgeData> neighbour in neighbours)
                {
                    _target.AddArc(neighbour.Key, vertex, neighbour.Value, null);
                }
            }

            // report the after contraction event.
            this.OnAfterContraction(vertex, edges);
        }
        /// <summary>
        /// Tests the set direction functionality for the given parameters.
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="forward"></param>
        /// <param name="backward"></param>
        /// <param name="toHigher"></param>
        private void DoTestSetDirection(CHEdgeData edge, bool forward, bool backward, bool toHigher)
        {
            edge.SetDirection(forward, backward, toHigher);

            if (forward) { Assert.IsTrue(edge.Forward); }
            else { Assert.IsFalse(edge.Forward); }
            if (backward) { Assert.IsTrue(edge.Backward); }
            else { Assert.IsFalse(edge.Backward); }
            if (toHigher) { Assert.IsTrue(edge.ToHigher); }
            else { Assert.IsFalse(edge.ToHigher); }
        }
Beispiel #5
0
        /// <summary>
        /// Contracts the given vertex.
        /// </summary>
        /// <param name="vertex"></param>
        public void Contract(uint vertex)
        {
            if (_contracted.Length > vertex && _contracted[vertex])
            {
                throw new Exception("Is already contracted!");
            }

            // keep the neighbours.
            var neighbours = new HashSet <KeyValuePair <uint, CHEdgeData> >();

            // get all information from the source.
            var edges = _target.GetEdges(vertex);

            // report the before contraction event.
            this.OnBeforeContraction(vertex, edges);

            // replace the adjacent edges with edges that are point up.
            var edgesForContractions = new List <KeyValuePair <uint, CHEdgeData> >(edges.Length);

            foreach (var edge in edges)
            {
                if (!edge.Value.ToLower && !edge.Value.ToHigher)
                { // the edge is not to lower or higher.
                    // use this edge for contraction.
                    edgesForContractions.Add(edge);

                    // overwrite the old edge making it point 'to higher' only.
                    _target.AddEdge(vertex, edge.Key,
                                    new CHEdgeData(edge.Value.Weight, edge.Value.Forward, edge.Value.Backward, true, edge.Value.ContractedVertexId, edge.Value.Tags), null);
                }
            }

            // loop over each combination of edges just once.
            for (int x = 1; x < edgesForContractions.Count; x++)
            { // loop over all elements first.
                var xEdge = edgesForContractions[x];

                for (int y = 0; y < x; y++)
                { // loop over all elements.
                    var yEdge = edgesForContractions[y];

                    // calculate the total weight.
                    var weight = xEdge.Value.Weight + yEdge.Value.Weight;

                    // add the combinations of these edges.
                    if (((xEdge.Value.Backward && yEdge.Value.Forward) ||
                         (yEdge.Value.Backward && xEdge.Value.Forward)) &&
                        (xEdge.Key != yEdge.Key))
                    { // there is a connection from x to y and there is no witness path.
                        var witnessXToY = _contractionWitnessCalculator.Exists(_target, xEdge.Key,
                                                                               yEdge.Key, vertex, weight, int.MaxValue);
                        var witnessYToX = _contractionWitnessCalculator.Exists(_target, yEdge.Key,
                                                                               xEdge.Key, vertex, weight, int.MaxValue);

                        // create x-to-y data and edge.
                        var dataXToY = new CHEdgeData();
                        var forward  = (xEdge.Value.Backward && yEdge.Value.Forward) &&
                                       !witnessXToY;
                        var backward = (yEdge.Value.Backward && xEdge.Value.Forward) &&
                                       !witnessYToX;
                        if ((forward || backward) ||
                            !_target.ContainsEdge(xEdge.Key, yEdge.Key))
                        { // add the edge if there is usefull info or if there needs to be a neighbour relationship.
                            dataXToY.SetDirection(forward, backward);
                            dataXToY.Weight             = weight;
                            dataXToY.ContractedVertexId = vertex;

                            _target.AddEdge(xEdge.Key, yEdge.Key, dataXToY, null, _comparer);
                        }
                    }
                }
            }

            // mark the vertex as contracted.
            this.MarkContracted(vertex);

            // notify a contracted neighbour.
            _calculator.NotifyContracted(vertex);

            // report the after contraction event.
            this.OnAfterContraction(vertex, edges);
        }