/// <summary> /// Calculates the edge-difference if u would be contracted. /// </summary> /// <param name="vertex"></param> /// <returns></returns> public float Calculate(uint vertex) { short contracted = 0; _contraction_count.TryGetValue(vertex, out contracted); // get the neighbours. var neighbours = _data.GetEdges(vertex); // simulate the construction of new edges. int new_edges = 0; int removed = neighbours.Length; // loop over all neighbours and check for witnesses. foreach (KeyValuePair <uint, CHEdgeData> from in neighbours) { // loop over all incoming neighbours if (!from.Value.Backward) { continue; } foreach (KeyValuePair <uint, CHEdgeData> to in neighbours) { // loop over all outgoing neighbours if (to.Key != from.Key && to.Value.Forward) { // the neighbours point to different vertices. // a new edge is needed. if (!_witness_calculator.Exists(_data, from.Key, to.Key, vertex, (float)from.Value.Weight + (float)to.Value.Weight, 1000)) { // no witness exists. new_edges++; } } } } // get the depth. long depth = 0; _depth.TryGetValue(vertex, out depth); return((((new_edges) - removed)) + (2 * contracted)); //return (new_edges - removed) + depth; }
/// <summary> /// Calculates the edge-difference if u would be contracted. /// </summary> /// <param name="vertex"></param> /// <returns></returns> public float Calculate(uint vertex) { // get the neighbours. var neighbours = _data.GetEdges(vertex); // simulate the construction of new edges. int newEdges = 0; int removed = 0; var edgesForContractions = new List <KeyValuePair <uint, CHEdgeData> >(neighbours.Length); foreach (var neighbour in neighbours) { if (!neighbour.Value.ToLower && !neighbour.Value.ToHigher) { edgesForContractions.Add(neighbour); removed++; } } // loop over all neighbours and check for witnesses. foreach (var from in edgesForContractions) { // loop over all incoming neighbours foreach (var to in edgesForContractions) { // loop over all outgoing neighbours if (to.Key != from.Key && to.Value.Forward && from.Value.Backward) { // the neighbours point to different vertices. // a new edge is needed. if (!_witnessCalculator.Exists(_data, from.Key, to.Key, vertex, (float)from.Value.Weight + (float)to.Value.Weight, 1000)) { // no witness exists. newEdges++; } } } } return((2 * newEdges) - removed); }
/// <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); }