16624 lines
564 KiB
C++
16624 lines
564 KiB
C++
/*
|
|
----
|
|
This file is part of SECONDO.
|
|
|
|
Copyright (C) 2016, University in Hagen, Department of Computer Science,
|
|
Database Systems for New Applications.
|
|
|
|
SECONDO is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
SECONDO is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty ofn
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with SECONDO; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
----
|
|
|
|
//paragraph [1] Title: [{\Large \bf \begin{center}] [\end{center}}]
|
|
//paragraph [10] Footnote: [{\footnote{] [}}]
|
|
//[TOC] [\tableofcontents]
|
|
|
|
[1] Implementation of Module HubLabeling Algebra
|
|
|
|
Maerz 2017 Sebastian Krings
|
|
|
|
[TOC]
|
|
|
|
1 Overview
|
|
|
|
The HubLabeling Algebra implements the HubLabeling Algorithm.
|
|
It offers some operators for creating the neccessary Hub-Labels over all nodes
|
|
and for doing shortest path queries on this structure.
|
|
|
|
2 Sourcecode of HubLabelingAlgebra
|
|
|
|
Within this sourcecode we provide three different approaches to implement
|
|
the HubLabeling (HL) algorithm and the Contraction Hierarchy (CH) algorithm
|
|
which is a part of the HubLabeling algorithm.
|
|
Basic input is the import of an OSM graph using the Secondo-Script
|
|
for importing OSM graphs.
|
|
In the following we describe those three approaches in short:
|
|
|
|
1) Persistent Approach
|
|
Within this approach most data, except for auxiliary, is kept within
|
|
the Secondo persistance structures like OrderedRelations and Relations.
|
|
Due to this the memory foodprint is very low.
|
|
But also due to this there are many expensive load-operations
|
|
which lead to very bad runtime perfomances.
|
|
Using this approach only is suitable for networks not greater than
|
|
1000 Edges.
|
|
One can use the following Secondo-Operators:
|
|
- hlCalcWeightsOrel
|
|
(calculates the edge costs by a fix set of speed limits per roadType
|
|
of the given OSM Graph)
|
|
- hlIterateOverAllNodesByRankAscAndDoContraction
|
|
(to create a contracted graph)
|
|
- hlCreateLabels
|
|
(create HubLabels on this contracted graph)
|
|
- hlQuery
|
|
(do a HL search on the HubLabels)
|
|
|
|
2) In-Memory Approach
|
|
Here all data is loaded into main memory and then be processed.
|
|
This increases of course memory footprint of some GB
|
|
(depends on the given networks size) but decreases runtime.
|
|
One can use the following Secondo-Operators:
|
|
- hlCalcWeightsOrel
|
|
(calculates the edge costs by a fix set of speed limits per roadType
|
|
of the given OSM Graph)
|
|
- hlDoContractionOfHlGraph
|
|
(to create a contracted graph)
|
|
- hlDoChSearchInHlGraph
|
|
(performs a CH search over the contracted hlGraph)
|
|
- hlCreateLabelsFromHlGraph
|
|
(create HubLabels on this contracted hlGraph)
|
|
- hlQuery
|
|
(do a HL search on the HubLabels)
|
|
|
|
3) In-Memory Approach using MainMemory2Algebra
|
|
Here we make use of the existing MainMemory2Algebra to process CH and HL
|
|
within main memory.
|
|
This Apporach is not yet implemented and do not work at the moment.
|
|
|
|
|
|
2.1 Defines, includes, and constants
|
|
|
|
*/
|
|
|
|
#include "Attribute.h" // implementation of attribute types
|
|
#include "Algebra.h" // definition of the algebra
|
|
#include "NestedList.h" // required at many places
|
|
#include "QueryProcessor.h" // needed for implementing value mappings
|
|
#include "AlgebraManager.h" // e.g., check for a certain kind
|
|
#include "Operator.h" // for operator creation
|
|
#include "StandardTypes.h" // priovides int, real, string, bool type
|
|
#include "Algebras/FText/FTextAlgebra.h"
|
|
#include "Symbols.h" // predefined strings
|
|
#include "ListUtils.h" // useful functions for nested lists
|
|
#include "Stream.h" // wrapper for secondo streams
|
|
|
|
|
|
#include "LogMsg.h" // send error messages
|
|
|
|
#include "../../Tools/Flob/DbArray.h" // use of DbArrays
|
|
|
|
#include "Algebras/Relation-C++/RelationAlgebra.h" // use of tuples
|
|
#include "Algebras/OrderedRelation/OrderedRelationAlgebra.h" // use of tuples
|
|
#include "Algebras/NestedRelation/NestedRelationAlgebra.h" // use of tuples
|
|
#include "Algebras/BTree/BTreeAlgebra.h" // use of tuples
|
|
#include "Algebras/Standard-C++/LongInt.h" // use of longint
|
|
#include "Algebras/Spatial/Point.h" // use of point
|
|
#include "Algebras/Spatial/SpatialAlgebra.h" // use of sline
|
|
|
|
#include <math.h> // required for some operators
|
|
#include <stack>
|
|
#include <limits>
|
|
#include <map>
|
|
|
|
#include <unordered_set>
|
|
#include <tuple>
|
|
|
|
|
|
#include "Algebras/MainMemory2/MainMemoryExt.h"
|
|
|
|
/*
|
|
2.2 Global Variables
|
|
|
|
Secondo uses some variables designed as singleton pattern. For accessing these
|
|
global variables, these variables have to be declared to be extern:
|
|
|
|
*/
|
|
|
|
extern NestedList *nl;
|
|
extern QueryProcessor *qp;
|
|
|
|
using namespace std;
|
|
|
|
/*
|
|
2.3 Namespace
|
|
|
|
Each algebra file defines a lot of functions. Thus, name conflicts may arise
|
|
with function names defined in other algebra modules during compiling/linking
|
|
the system. To avoid these conflicts, the algebra implementation should be
|
|
embedded into a namespace.
|
|
|
|
*/
|
|
|
|
namespace hublabeling
|
|
{
|
|
|
|
/*
|
|
2.4 Logging
|
|
|
|
We provide some console outputs through very simple logging.
|
|
It provides levels of error, debug and info
|
|
|
|
*/
|
|
//Debug
|
|
//#define USEDEBUG
|
|
|
|
#ifdef USEDEBUG
|
|
#define LogDebug(x) std::cout << x
|
|
#else
|
|
#define LogDebug(x)
|
|
#endif
|
|
|
|
|
|
//Info
|
|
#define USEINFO
|
|
|
|
#ifdef USEINFO
|
|
#define LogInfo(x) std::cout << x
|
|
#else
|
|
#define LogInfo(x)
|
|
#endif
|
|
|
|
|
|
//Error
|
|
#define USEERROR
|
|
|
|
#ifdef USEERROR
|
|
#define LogError(x) std::cout << x
|
|
#else
|
|
#define LogError(x)
|
|
#endif
|
|
|
|
|
|
//Performance measure
|
|
#define USEPERF
|
|
|
|
#ifdef USEPERF
|
|
#define LogPerf(x) std::cout << std::setprecision (2) << x
|
|
#else
|
|
#define LogPerf(x)
|
|
#endif
|
|
|
|
|
|
/*
|
|
2.5 Auxilary Classes
|
|
|
|
Some functionality uses special defined classes to store information
|
|
during processing.
|
|
|
|
*/
|
|
|
|
/*
|
|
This class provides a structure to represent an edge out of the hlGraph
|
|
which is the in memory representation of the underlying network to process.
|
|
This class is used by the (2) In-Memory Approach.
|
|
|
|
An edge here is stored space efficient by storing edges as they are
|
|
and additionally the same edges a second time but in reverse manner.
|
|
|
|
Functions related to 'forward' mean the original edge as it is and
|
|
'reverse' relates to the reverse edges.
|
|
|
|
*/
|
|
class HlEdgeEntry
|
|
{
|
|
public:
|
|
// constructor doing nothing
|
|
HlEdgeEntry() {}
|
|
// destructor
|
|
~HlEdgeEntry() {}
|
|
|
|
int getTargetIndex() const
|
|
{
|
|
return targetIndex;
|
|
}
|
|
int getParentIndexForward() const
|
|
{
|
|
return parentIndexForward;
|
|
}
|
|
int getParentIndexReverse() const
|
|
{
|
|
return parentIndexReverse;
|
|
}
|
|
double getWeightForward() const
|
|
{
|
|
return weightForward;
|
|
}
|
|
double getWeightReverse() const
|
|
{
|
|
return weightReverse;
|
|
}
|
|
bool getIsForward() const
|
|
{
|
|
return isForward;
|
|
}
|
|
bool getIsReverse() const
|
|
{
|
|
return isReverse;
|
|
}
|
|
bool getIsUpwardOriginal() const
|
|
{
|
|
return isUpwardOriginal;
|
|
}
|
|
|
|
void setTargetIndex(const int _targetIndex)
|
|
{
|
|
targetIndex = _targetIndex;
|
|
}
|
|
|
|
/*
|
|
* A parent here is the node v which was contracted
|
|
* and then replaced by this shortcutedge.
|
|
*/
|
|
void setParentIndexForward(const int _parentIndexForward)
|
|
{
|
|
parentIndexForward = _parentIndexForward;
|
|
}
|
|
|
|
/*
|
|
* A parent here is the node v which was contracted
|
|
* and then replaced by this shortcutedge.
|
|
*/
|
|
void setParentIndexReverse(const int _parentIndexReverse)
|
|
{
|
|
parentIndexReverse = _parentIndexReverse;
|
|
}
|
|
void setWeightForward(const double _weightForward)
|
|
{
|
|
weightForward = _weightForward;
|
|
}
|
|
void setWeightReverse(const double _weightReverse)
|
|
{
|
|
weightReverse = _weightReverse;
|
|
}
|
|
void setIsForward(const bool _isForward)
|
|
{
|
|
isForward = _isForward;
|
|
}
|
|
void setIsReverse(const bool _isReverse)
|
|
{
|
|
isReverse = _isReverse;
|
|
}
|
|
void setIsUpwardOriginal(const bool _isUpwardOriginal)
|
|
{
|
|
isUpwardOriginal = _isUpwardOriginal;
|
|
}
|
|
|
|
private:
|
|
|
|
int targetIndex = -1;
|
|
int parentIndexForward = -1; //used for shortcuts
|
|
int parentIndexReverse = -1; //used for shortcuts
|
|
double weightForward = -1.0;
|
|
double weightReverse = -1.0;
|
|
bool isForward = false;
|
|
bool isReverse = false;
|
|
bool isUpwardOriginal = false;
|
|
};
|
|
|
|
/*
|
|
This class provides a structure to represent an node out of the hlGraph
|
|
which is the in memory representation of the underlying network to process.
|
|
This class is used by the (2) In-Memory Approach.
|
|
|
|
A node consists of a nodeId, the nodes Rank and a vector of adjacent edges.
|
|
|
|
|
|
*/
|
|
class HlNodeEntry
|
|
{
|
|
public:
|
|
// constructor doing nothing
|
|
HlNodeEntry() {}
|
|
// destructor
|
|
~HlNodeEntry() {}
|
|
|
|
int getNodeId() const
|
|
{
|
|
return nodeId;
|
|
}
|
|
int getRankValue() const
|
|
{
|
|
return rankValue;
|
|
}
|
|
std::vector<HlEdgeEntry*>* getEdgesVector() const
|
|
{
|
|
return edgesVector;
|
|
}
|
|
|
|
void setNodeId(const int _nodeId)
|
|
{
|
|
nodeId = _nodeId;
|
|
}
|
|
void setRankValue(const int _rankValue)
|
|
{
|
|
rankValue = _rankValue;
|
|
}
|
|
void setEdgesVector(std::vector<HlEdgeEntry*>* _edgesVector)
|
|
{
|
|
edgesVector = _edgesVector;
|
|
}
|
|
|
|
private:
|
|
|
|
int nodeId = -1;
|
|
int rankValue = -1;
|
|
std::vector<HlEdgeEntry*>* edgesVector = 0;
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
This class provides a structure to represent a node out of the searchTree
|
|
resulting from an CH search.
|
|
|
|
The search tree is space efficient in that way that that a visitedNode,
|
|
represented by this class, stores information of forward- and reversesearch
|
|
within the same object if both searches visit the same nodes.
|
|
This for there are functions for every of those both search spaces.
|
|
|
|
A predecessor here means to be the node which directly comes before the
|
|
current node on the shortest path from the source
|
|
of this forward- or reversesearch.
|
|
Using this one can resolve the path recursively back to the source node,
|
|
which has no valid predecessor (= -1).
|
|
|
|
This class is used by the (2) In-Memory Approach.
|
|
|
|
|
|
*/
|
|
class ChNode
|
|
{
|
|
public:
|
|
// constructor doing nothing
|
|
ChNode() {}
|
|
// destructor
|
|
~ChNode() {}
|
|
|
|
|
|
double getDistForward() const
|
|
{
|
|
return distForward;
|
|
}
|
|
double getDistReverse() const
|
|
{
|
|
return distReverse;
|
|
}
|
|
int getPredecessorIndexForward() const
|
|
{
|
|
return predecessorIndexForward;
|
|
}
|
|
int getPredecessorIndexReverse() const
|
|
{
|
|
return predecessorIndexReverse;
|
|
}
|
|
|
|
void setDistForward(const double _distForward)
|
|
{
|
|
distForward = _distForward;
|
|
}
|
|
void setDistReverse(const double _distReverse)
|
|
{
|
|
distReverse = _distReverse;
|
|
}
|
|
void setPredecessorIndexForward(const int _predecessorIndexForward)
|
|
{
|
|
predecessorIndexForward = _predecessorIndexForward;
|
|
}
|
|
void setPredecessorIndexReverse(const int _predecessorIndexReverse)
|
|
{
|
|
predecessorIndexReverse = _predecessorIndexReverse;
|
|
}
|
|
|
|
private:
|
|
|
|
|
|
double distForward = 0.0;
|
|
double distReverse = 0.0;
|
|
int predecessorIndexForward = -1;
|
|
int predecessorIndexReverse = -1;
|
|
};
|
|
|
|
|
|
/*
|
|
3 The Class HubLabelClass
|
|
|
|
This class is used to provide basic structures to handle HubLabels
|
|
and to privide functionality to create such ones.
|
|
|
|
-A given Graph can be modified with auxiliary attributes.
|
|
-The graph can be contracted.
|
|
-The graph can be divided into upwards- and downwards graphs.
|
|
-HubLabels can be created.
|
|
-A HubLabeling Search can be performed.
|
|
|
|
There are several operators for doing this.
|
|
|
|
3.1 Basic HubLabeling structures
|
|
|
|
*/
|
|
class HubLabelClass
|
|
{
|
|
public:
|
|
// constructor doing nothing
|
|
HubLabelClass() {}
|
|
// constructor initializing the object
|
|
HubLabelClass(const double _x, const double _y,
|
|
const double _r):
|
|
x(_x), y(_y), r(_r) {}
|
|
// destructor
|
|
~HubLabelClass() {}
|
|
static const string BasicType()
|
|
{
|
|
return "HubLabelClass";
|
|
}
|
|
// the checktype function for non-nested types looks always
|
|
// the same
|
|
static const bool checkType(const ListExpr list)
|
|
{
|
|
return listutils::isSymbol(list, BasicType());
|
|
}
|
|
|
|
double getX() const
|
|
{
|
|
return x;
|
|
}
|
|
double getY() const
|
|
{
|
|
return y;
|
|
}
|
|
double getR() const
|
|
{
|
|
return r;
|
|
}
|
|
|
|
int getProgressInterval() const
|
|
{
|
|
return progressInterval;
|
|
}
|
|
|
|
void setProgressInterval(int _progressInterval)
|
|
{
|
|
int tmpVal = _progressInterval;
|
|
if(tmpVal < 1)
|
|
{
|
|
tmpVal = 1;
|
|
}
|
|
progressInterval = tmpVal;
|
|
}
|
|
|
|
|
|
/*
|
|
* function to receive the current time in milliseconds
|
|
*/
|
|
double getCurrentTimeInMs() const
|
|
{
|
|
struct timeval tp;
|
|
gettimeofday(&tp, NULL);
|
|
//get current timestamp in milliseconds
|
|
long nsLong = (long) tp.tv_sec * 1000L * 1000L + tp.tv_usec;
|
|
double msDouble = (double) nsLong / 1000;
|
|
|
|
#ifdef USEDEBUG
|
|
#ifdef USEPERF
|
|
LogPerf("current time in nanoseconds: "
|
|
<< nsLong << " in milliseconds: " << fixed << msDouble << endl);
|
|
#endif
|
|
#endif
|
|
|
|
return msDouble;
|
|
}
|
|
|
|
/*
|
|
|
|
3.2 HubLabeling functionality of (1) Persistent Approach
|
|
|
|
*/
|
|
|
|
/*
|
|
* Definition of CostModes.
|
|
* Used for getting shortest paths by different cost-calculations.
|
|
*/
|
|
static const int HL_DEFAULT_COST_MODE = 1;
|
|
static const int HL_LENGTH_COST_MODE = 2;
|
|
static const int HL_TIME_COST_MODE = 3;
|
|
|
|
/*
|
|
* Gets the weightedCosts of a given edge.
|
|
* Differences between several cost modes to calculate the weighted
|
|
* costs of edges.
|
|
*
|
|
* !TODO: Currently does not support different cost modes
|
|
* but extracts the weighted costs directly from the given edge
|
|
* independently of the given cost mode using the Tuple-field
|
|
* on index position like @see HL_INDEX_OF_COSTS_IN_EDGE_TUPLE
|
|
*
|
|
* @param costMode Defines the cost mode with which the weighted
|
|
* costs will be calculated
|
|
* uses @see HL_DEFAULT_COST_MODE when a value of -1 is given
|
|
* @param currentEdge The edge for which the weighted costs shall
|
|
* be calculated/ extracted from
|
|
* @return the calculated/ extracted weighted costs
|
|
*/
|
|
double hlGetWeightedCost(int costMode,
|
|
Tuple* currentEdge) const
|
|
{
|
|
double calculatedDistance = -1;
|
|
if(costMode == -1)
|
|
{
|
|
costMode = HL_DEFAULT_COST_MODE;
|
|
}
|
|
CcReal* currentEdgeCost = (CcReal*)
|
|
currentEdge->GetAttribute(
|
|
HL_INDEX_OF_COSTS_IN_EDGE_TUPLE);
|
|
|
|
calculatedDistance =
|
|
currentEdgeCost->GetRealval();
|
|
|
|
return calculatedDistance;
|
|
}
|
|
|
|
/*
|
|
* Definition of Calculation Functions used to calculate the rank
|
|
* of a vertex inside the underlying graph.
|
|
*/
|
|
static const int HL_DEFAULT_CALC_FUNCTION = 1;
|
|
|
|
/*
|
|
* Calculcates the ranking for he current vertext by either a given
|
|
* calculation function
|
|
* or else by the default calculation function.
|
|
*
|
|
* !TODO:
|
|
* Supported Calculation Functions are:
|
|
* @see HL_DEFAULT_CALC_FUNCTION
|
|
* calculates a ration of (countIncomingEdges *
|
|
* countOutgoingEdges) / (countIncomingEdges + countOutgoingEdges)
|
|
*
|
|
* @param orelEdgesSource is an OrderedRelation containging all
|
|
* edges of the underlying graph sorted by the field Source
|
|
* @param orelEdgesTarget is an OrderedRelation containging all
|
|
* edges of the underlying graph sorted by the field Target
|
|
* @param calcFunctionHL defines the calculationFunction to be used
|
|
* to calculate the rank, uses @see HL_DEFAULT_CALC_FUNCTION when
|
|
* a value of < 1 has been given
|
|
* @param currentVertexId is the ID of the current vertex the rank
|
|
* shall be calculated for
|
|
* @return the calculatedRank
|
|
*/
|
|
double hlCalcRank(OrderedRelation* orelEdgesSource,
|
|
OrderedRelation* orelEdgesTarget,
|
|
int calcFunctionHL,
|
|
CcInt* currentVertexId) const
|
|
{
|
|
//XXTODO: muss der rank nicht eindeutig sein?
|
|
double calculatedRank = -1;
|
|
|
|
//Standard Funktion verwenden
|
|
if(calcFunctionHL < 1)
|
|
{
|
|
calcFunctionHL = HL_DEFAULT_CALC_FUNCTION;
|
|
}
|
|
|
|
if(calcFunctionHL == HL_DEFAULT_CALC_FUNCTION)
|
|
{
|
|
int countIncomingEdges = 0;
|
|
int countOutgoingEdges = 0;
|
|
int countEdgesToBeDeleted = 0;
|
|
int countShortcutsToBeCreated = 0;
|
|
double shortcutsPerAdjNodeRatio = 0;
|
|
|
|
std::vector<void*> vecAttributesFrom(1);
|
|
vecAttributesFrom[0] = currentVertexId;
|
|
std::vector<SmiKey::KeyDataType> vecAttrTypesFrom(
|
|
1);
|
|
vecAttrTypesFrom[0] =
|
|
currentVertexId->getSMIKeyType();
|
|
CompositeKey from(vecAttributesFrom,
|
|
vecAttrTypesFrom,
|
|
false);
|
|
|
|
CcInt currentVertexIdPlusOne(true,
|
|
currentVertexId->GetIntval() + 1);
|
|
CcInt* currentVertexIdPlusOnePtr =
|
|
¤tVertexIdPlusOne;
|
|
std::vector<void*> vecAttributesTo(1);
|
|
vecAttributesTo[0] = currentVertexIdPlusOnePtr;
|
|
std::vector<SmiKey::KeyDataType> vecAttrTypesTo(
|
|
1);
|
|
vecAttrTypesTo[0] =
|
|
currentVertexIdPlusOnePtr->getSMIKeyType();
|
|
CompositeKey to(vecAttributesTo, vecAttrTypesTo,
|
|
false);
|
|
|
|
//get all outgoing edges
|
|
GenericRelationIterator* relEdgesSourceIter =
|
|
orelEdgesSource->MakeRangeScan(from, to);
|
|
|
|
//Get first Tuple
|
|
Tuple* currentEdgeSourceTupleS =
|
|
relEdgesSourceIter->GetNextTuple();
|
|
|
|
//Iterate over all Tuples
|
|
while(currentEdgeSourceTupleS)
|
|
{
|
|
countOutgoingEdges++;
|
|
|
|
currentEdgeSourceTupleS->DeleteIfAllowed();
|
|
currentEdgeSourceTupleS = 0;
|
|
currentEdgeSourceTupleS =
|
|
relEdgesSourceIter->GetNextTuple();
|
|
}
|
|
delete relEdgesSourceIter;
|
|
|
|
//get all incoming edges
|
|
GenericRelationIterator* relEdgesTargetIter =
|
|
orelEdgesTarget->MakeRangeScan(from, to);
|
|
|
|
//Get first Tuple
|
|
Tuple* currentEdgeTargetTupleT =
|
|
relEdgesTargetIter->GetNextTuple();
|
|
|
|
//Iterate over all Tuples
|
|
while(currentEdgeTargetTupleT)
|
|
{
|
|
countIncomingEdges++;
|
|
|
|
currentEdgeTargetTupleT->DeleteIfAllowed();
|
|
currentEdgeTargetTupleT = 0;
|
|
currentEdgeTargetTupleT =
|
|
relEdgesTargetIter->GetNextTuple();
|
|
}
|
|
delete relEdgesTargetIter;
|
|
|
|
//Do calculation
|
|
countEdgesToBeDeleted =
|
|
countIncomingEdges + countOutgoingEdges;
|
|
countShortcutsToBeCreated = countIncomingEdges *
|
|
(countOutgoingEdges - 1);
|
|
|
|
if(countEdgesToBeDeleted != 0)
|
|
{
|
|
shortcutsPerAdjNodeRatio = (double)
|
|
countShortcutsToBeCreated / countEdgesToBeDeleted;
|
|
}
|
|
calculatedRank = shortcutsPerAdjNodeRatio;
|
|
}
|
|
|
|
return calculatedRank;
|
|
}
|
|
|
|
|
|
/*
|
|
* OrderedRelation type for the returnType of the
|
|
* OneHopReverseSearch
|
|
* Used for creation of new OrderedRelation Objects, new Tuples of
|
|
* this OrderedRelation or cloning or deleting of an
|
|
* OrderedRelation of this type
|
|
*/
|
|
static const string
|
|
hlGetOneHopReverseOrelIdTypeInfo()
|
|
{
|
|
return "(" + OrderedRelation::BasicType() +
|
|
"(" + Tuple::BasicType() +
|
|
"(" +
|
|
"(NodeIdSourceReverseX " + CcInt::BasicType()
|
|
+ ")" +
|
|
"(NodeIdTargetT " + CcInt::BasicType() + ")" +
|
|
"(WeightedCosts " + CcReal::BasicType() + ")" +
|
|
")" +
|
|
")" +
|
|
"(NodeIdSourceReverseX)" +
|
|
")";
|
|
}
|
|
|
|
|
|
/*
|
|
* OrderedRelation type for Edges ordered by Source
|
|
* Used for creation of new OrderedRelation Objects, new Tuples of
|
|
* this OrderedRelation or cloning or deleting of an
|
|
* OrderedRelation of this type
|
|
*/
|
|
static const string hlGetEdgesOrelSourceTypeInfo()
|
|
{
|
|
return "(" + Relation::BasicType() +
|
|
hlGetEdgesTupleTypeInfo() +
|
|
"(Source)" +
|
|
")";
|
|
}
|
|
|
|
|
|
/*
|
|
* OrderedRelation type for Edges ordered by Target
|
|
* Used for creation of new OrderedRelation Objects, new Tuples of
|
|
* this OrderedRelation or cloning or deleting of an
|
|
* OrderedRelation of this type
|
|
*/
|
|
static const string hlGetEdgesOrelTargetTypeInfo()
|
|
{
|
|
return "(" + OrderedRelation::BasicType() +
|
|
hlGetEdgesTupleTypeInfo() +
|
|
"(Target)" +
|
|
")";
|
|
}
|
|
|
|
|
|
/*
|
|
* Relation type for Edges
|
|
* Used for creation of new Relation Objects, new Tuples of this
|
|
* Relation or cloning or deleting of an Relation of this type
|
|
*/
|
|
static const string hlGetEdgesRelTypeInfo()
|
|
{
|
|
return "(" + Relation::BasicType() +
|
|
hlGetEdgesTupleTypeInfo() +
|
|
")";
|
|
}
|
|
|
|
|
|
/*
|
|
* TupleType type for Edges
|
|
*/
|
|
static const string hlGetEdgesTupleTypeInfo()
|
|
{
|
|
return "(" + Tuple::BasicType() +
|
|
"(" +
|
|
"(Source " + CcInt::BasicType() + ")" +
|
|
"(Target " + CcInt::BasicType() + ")" +
|
|
"(SourcePos " + Point::BasicType() + ")" +
|
|
"(TargetPos " + Point::BasicType() + ")" +
|
|
"(SourceNodeCounter " + CcInt::BasicType() + ")" +
|
|
"(TargetNodeCounter " + CcInt::BasicType() + ")" +
|
|
"(Curve " + SimpleLine::BasicType() + ")" +
|
|
"(RoadName " + FText::BasicType() + ")" +
|
|
"(RoadType " + FText::BasicType() + ")" +
|
|
"(WayId " + LongInt::BasicType() + ")" +
|
|
"(Costs " + CcReal::BasicType() + ")" +
|
|
"(HlShortcutViaParent " + CcInt::BasicType() + ")"
|
|
+
|
|
")" +
|
|
")";
|
|
}
|
|
|
|
|
|
/*
|
|
* Definition of Field-Indexes for edgesOrel and oneHopReverseOrel
|
|
*/
|
|
static const int HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE
|
|
= 0;
|
|
static const int HL_INDEX_OF_TARGET_IN_EDGE_TUPLE
|
|
= 1;
|
|
static const int
|
|
HL_INDEX_OF_SOURCE_POS_IN_EDGE_TUPLE = 2;
|
|
static const int
|
|
HL_INDEX_OF_TARGET_POS_IN_EDGE_TUPLE = 3;
|
|
static const int
|
|
HL_INDEX_OF_SOURCE_NODE_COUNTER_IN_EDGE_TUPLE = 4;
|
|
static const int
|
|
HL_INDEX_OF_TARGET_NODE_COUNTER_IN_EDGE_TUPLE = 5;
|
|
static const int HL_INDEX_OF_CURVE_IN_EDGE_TUPLE =
|
|
6;
|
|
static const int
|
|
HL_INDEX_OF_ROAD_NAME_IN_EDGE_TUPLE = 7;
|
|
static const int
|
|
HL_INDEX_OF_ROAD_TYPE_IN_EDGE_TUPLE = 8;
|
|
static const int HL_INDEX_OF_WAY_ID_IN_EDGE_TUPLE
|
|
= 9;
|
|
static const int HL_INDEX_OF_COSTS_IN_EDGE_TUPLE =
|
|
10;
|
|
static const int
|
|
HL_INDEX_OF_PARENT_ID_IN_EDGE_TUPLE = 11;
|
|
static const int
|
|
HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE = 0;
|
|
static const int
|
|
HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE = 1;
|
|
static const int
|
|
HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE = 2;
|
|
|
|
/*
|
|
* Processes a one-hop reverse search for every target-node
|
|
* reachable from v.
|
|
* That means that there exists an outgoing edge from v to t.
|
|
*
|
|
* For every of those vertexes t an own one-hop reverse search is
|
|
* done.
|
|
* There all vertexes x with an incoming edge e(x, t) to t are
|
|
* stored with the distance of e(x, t) into the given
|
|
* OrderedRelation ordered by the vertex ID of x.
|
|
* All distances of all iterations done within this function call
|
|
* are stored together in the same orel such that there will be
|
|
* only one orel (the given one) for the given vertex v to be
|
|
* contracted.
|
|
*
|
|
* @param orelEdgesSource is an OrderedRelation containging all
|
|
* edges of the underlying graph sorted by the field Source
|
|
* @param orelEdgesTarget is an OrderedRelation containging all
|
|
* edges of the underlying graph sorted by the field Target
|
|
* @param currentVertexIdRevV the current vertex v to be contracted
|
|
* @param oneHopReverseMultiMap the Ordered map by reference where
|
|
* all distances found by the reverse search will be stored in
|
|
* @return true, since the result of this function will be stored
|
|
* directly in @see oneHopReverseMultiMap
|
|
*
|
|
*/
|
|
bool hlOneHopReverseSearch(OrderedRelation*
|
|
orelEdgesSource,
|
|
OrderedRelation* orelEdgesTarget,
|
|
CcInt* currentVertexIdRevV,
|
|
std::multimap<int, std::tuple<int, double>>
|
|
&oneHopReverseMultiMap
|
|
) const
|
|
{
|
|
std::vector<void*> vecAttributesFromRevV(1);
|
|
vecAttributesFromRevV[0] = currentVertexIdRevV;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesFromRevV(1);
|
|
vecAttrTypesFromRevV[0] =
|
|
currentVertexIdRevV->getSMIKeyType();
|
|
CompositeKey fromRevV(vecAttributesFromRevV,
|
|
vecAttrTypesFromRevV, false);
|
|
|
|
CcInt currentVertexIdPlusOneRevV(true,
|
|
currentVertexIdRevV->GetIntval() + 1);
|
|
CcInt* currentVertexIdPlusOnePtrRevV =
|
|
¤tVertexIdPlusOneRevV;
|
|
std::vector<void*> vecAttributesToRevV(1);
|
|
vecAttributesToRevV[0] =
|
|
currentVertexIdPlusOnePtrRevV;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesToRevV(1);
|
|
vecAttrTypesToRevV[0] =
|
|
currentVertexIdPlusOnePtrRevV->getSMIKeyType();
|
|
CompositeKey toRevV(vecAttributesToRevV,
|
|
vecAttrTypesToRevV,
|
|
false);
|
|
|
|
//get all outgoing edges (v, t)
|
|
GenericRelationIterator* relEdgesSourceIterRevVT =
|
|
orelEdgesSource->MakeRangeScan(fromRevV, toRevV);
|
|
|
|
//Get first Tuple
|
|
Tuple* currentEdgeSourceTupleRevVT =
|
|
relEdgesSourceIterRevVT->GetNextTuple();
|
|
|
|
//Iterate over all Outgoing Tuples
|
|
while(currentEdgeSourceTupleRevVT)
|
|
{
|
|
CcInt* currentTargetNodeRevT = (CcInt*)
|
|
currentEdgeSourceTupleRevVT->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
|
|
//Process current iteration
|
|
hlOneHopReverseSearchProcessIncomingEdges(
|
|
orelEdgesTarget,
|
|
oneHopReverseMultiMap, currentTargetNodeRevT);
|
|
|
|
currentEdgeSourceTupleRevVT->DeleteIfAllowed();
|
|
currentEdgeSourceTupleRevVT = 0;
|
|
currentEdgeSourceTupleRevVT =
|
|
relEdgesSourceIterRevVT->GetNextTuple();
|
|
}
|
|
delete relEdgesSourceIterRevVT;
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Procession of inner iteration of reverse search
|
|
* ( @see hlOneHopReverseSearch)
|
|
* over all vertexes x incoming to the current vertext t.
|
|
*
|
|
* @param orelEdgesTarget is an OrderedRelation containging all
|
|
* edges of the underlying graph sorted by the field Target
|
|
* @param oneHopReverseMultiMap the ordered map by reference where
|
|
* all distances found by the reverse search will be stored in
|
|
* @param currentTargetNodeRevT the current vertex t reachable
|
|
* from v
|
|
* @return true, since the result of this function will be stored
|
|
* directly in @see oneHopReverseMultiMap
|
|
*
|
|
*/
|
|
bool hlOneHopReverseSearchProcessIncomingEdges(
|
|
OrderedRelation* orelEdgesTarget,
|
|
std::multimap<int, std::tuple<int, double>>
|
|
&oneHopReverseMultiMap,
|
|
CcInt* currentTargetNodeRevT) const
|
|
{
|
|
std::vector<void*> vecAttributesFromRevT(1);
|
|
vecAttributesFromRevT[0] = currentTargetNodeRevT;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesFromRevT(1);
|
|
vecAttrTypesFromRevT[0] =
|
|
currentTargetNodeRevT->getSMIKeyType();
|
|
CompositeKey fromRevT(vecAttributesFromRevT,
|
|
vecAttrTypesFromRevT, false);
|
|
|
|
CcInt currentTargetNodePlusOneRevT(true,
|
|
currentTargetNodeRevT->GetIntval() + 1);
|
|
CcInt* currentTargetNodePlusOnePtrRevT =
|
|
¤tTargetNodePlusOneRevT;
|
|
std::vector<void*> vecAttributesToRevT(1);
|
|
vecAttributesToRevT[0] =
|
|
currentTargetNodePlusOnePtrRevT;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesToRevT(1);
|
|
vecAttrTypesToRevT[0] =
|
|
currentTargetNodePlusOnePtrRevT->getSMIKeyType();
|
|
CompositeKey toRevT(vecAttributesToRevT,
|
|
vecAttrTypesToRevT, false);
|
|
|
|
//get all incoming edges (u, t)
|
|
GenericRelationIterator* relEdgesTargetIterUT =
|
|
orelEdgesTarget->MakeRangeScan(fromRevT, toRevT);
|
|
|
|
//Get first Tuple u
|
|
Tuple* currentEdgeTargetTupleU =
|
|
relEdgesTargetIterUT->GetNextTuple();
|
|
|
|
//Iterate over all Incoming Tuples u
|
|
#ifdef USEDEBUG
|
|
int i = 0;
|
|
#endif
|
|
while(currentEdgeTargetTupleU)
|
|
{
|
|
//Dont ignore current Node to be contracted because
|
|
//we need its distances also in forward search
|
|
CcInt* currentSourceNodeU = (CcInt*)
|
|
currentEdgeTargetTupleU->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
double currentDistXT = hlGetWeightedCost(
|
|
HL_DEFAULT_COST_MODE, currentEdgeTargetTupleU);
|
|
#ifdef USEDEBUG
|
|
LogDebug(i++ << ": (" <<
|
|
currentSourceNodeU->GetIntval() << ";" <<
|
|
currentTargetNodeRevT->GetIntval() << ";" <<
|
|
currentDistXT << "), " << endl);
|
|
#endif
|
|
|
|
bool doInsertNewXT = true;
|
|
|
|
//Check whether there still is an edge XT and which one is
|
|
//shorter, keep the shortest of both (may update the existing one)
|
|
std::pair <std::multimap<int, std::tuple<int, double>>::iterator,
|
|
std::multimap<int, std::tuple<int, double>>::iterator>
|
|
revXTRangeBoundsIter;
|
|
revXTRangeBoundsIter =
|
|
oneHopReverseMultiMap.equal_range(
|
|
currentSourceNodeU->GetIntval());
|
|
|
|
for (std::multimap<int, std::tuple<int, double>>::iterator
|
|
revXTRangeIter = revXTRangeBoundsIter.first;
|
|
revXTRangeIter != revXTRangeBoundsIter.second;
|
|
++revXTRangeIter)
|
|
{
|
|
std::tuple<int, double> lookupTupleXT =
|
|
(*revXTRangeIter).second;
|
|
int lookupEdgeIdT =
|
|
std::get<HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE -
|
|
1>(lookupTupleXT);
|
|
double lookupEdgeDistXT =
|
|
std::get<HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE - 1>
|
|
(lookupTupleXT);
|
|
|
|
if(currentTargetNodeRevT->GetIntval() ==
|
|
lookupEdgeIdT)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("XT still exists" << endl);
|
|
#endif
|
|
if(currentDistXT < lookupEdgeDistXT)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("still existing XT is longer,"
|
|
" going to delete it"
|
|
" here to insert the current new XT afterwards"
|
|
<< endl );
|
|
#endif
|
|
oneHopReverseMultiMap.erase(revXTRangeIter);
|
|
}
|
|
else
|
|
{
|
|
//do not insert current new XT, its longer
|
|
// than the existing one
|
|
doInsertNewXT = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(doInsertNewXT)
|
|
{
|
|
std::tuple<int, double> insertTuple =
|
|
std::make_tuple(
|
|
currentTargetNodeRevT->GetIntval(),
|
|
currentDistXT);
|
|
oneHopReverseMultiMap.insert(
|
|
pair<int, std::tuple<int, double>>
|
|
(currentSourceNodeU->GetIntval(), insertTuple));
|
|
}
|
|
|
|
//Free Incoming-Iteration
|
|
currentEdgeTargetTupleU->DeleteIfAllowed();
|
|
currentEdgeTargetTupleU = 0;
|
|
currentEdgeTargetTupleU =
|
|
relEdgesTargetIterUT->GetNextTuple();
|
|
}
|
|
if(oneHopReverseMultiMap.size() > 10)
|
|
{
|
|
//sleep(1000 * 1000 * 10);
|
|
}
|
|
delete relEdgesTargetIterUT;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* OrderedRelation type for shortcuts to be created,
|
|
* identified during the contraction.
|
|
* Used for creation of new OrderedRelation Objects,
|
|
* new Tuples of this OrderedRelation
|
|
* or cloning or deleting of an OrderedRelation of this type
|
|
*/
|
|
static const string
|
|
hlGetShortcutsCreatedSourceTypeInfo()
|
|
{
|
|
return "(" + OrderedRelation::BasicType() +
|
|
"(" + Tuple::BasicType() +
|
|
"(" +
|
|
"(Source " + CcInt::BasicType() + ")" +
|
|
"(Target " + CcInt::BasicType() + ")" +
|
|
"(Dist " + CcReal::BasicType() + ")" +
|
|
"(ParentVia " + CcInt::BasicType() + ")" +
|
|
")" +
|
|
")" +
|
|
"(Source)" +
|
|
")";
|
|
}
|
|
|
|
/*
|
|
* Definition of Field-Indexes for shortcuts-orel
|
|
*/
|
|
static const int
|
|
HL_INDEX_OF_SOURCE_IN_SHORTCUT_TUPLE = 0;
|
|
static const int
|
|
HL_INDEX_OF_TARGET_IN_SHORTCUT_TUPLE = 1;
|
|
static const int
|
|
HL_INDEX_OF_DIST_IN_SHORTCUT_TUPLE = 2;
|
|
static const int
|
|
HL_INDEX_OF_PARENT_ID_IN_SHORTCUT_TUPLE = 3;
|
|
|
|
/*
|
|
* OrderedRelation type for vertices scanned but not yet visited
|
|
* during forward search.
|
|
* Used for creation of new OrderedRelation Objects, new Tuples
|
|
* of this OrderedRelation
|
|
* or cloning or deleting of an OrderedRelation of this type
|
|
*/
|
|
static const string
|
|
hlGetNotYetVisitedNodesTypeInfo()
|
|
{
|
|
return "(" + OrderedRelation::BasicType() +
|
|
"(" + Tuple::BasicType() +
|
|
"(" +
|
|
"(Dist " + CcReal::BasicType() + ")" +
|
|
"(NodeId " + CcInt::BasicType() + ")" +
|
|
"(HopDepth " + CcInt::BasicType() + ")" +
|
|
")" +
|
|
")" +
|
|
"(Dist)" +
|
|
")";
|
|
}
|
|
|
|
/*
|
|
* Definition of Field-Indexes for notYetVisitedNodes-orel
|
|
*/
|
|
static const int
|
|
HL_INDEX_OF_DIST_IN_NOT_YET_VISITED = 0;
|
|
static const int
|
|
HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED = 1;
|
|
static const int
|
|
HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED = 2;
|
|
|
|
/*
|
|
* Definition of default h-hop-size
|
|
*/
|
|
static const int HL_DEFAULT_H_DEPTH = 1;
|
|
|
|
/*
|
|
* OrderedRelation type for vertices still visited during forward search.
|
|
* Used for creation of new OrderedRelation Objects, new Tuples
|
|
* of this OrderedRelation
|
|
* or cloning or deleting of an OrderedRelation of this type
|
|
*/
|
|
static const string
|
|
hlGetStillVisitedNodesTypeInfo()
|
|
{
|
|
return "(" + OrderedRelation::BasicType() +
|
|
"(" + Tuple::BasicType() +
|
|
"(" +
|
|
"(NodeId " + CcInt::BasicType() + ")" +
|
|
")" +
|
|
")" +
|
|
"(NodeId)" +
|
|
")";
|
|
}
|
|
|
|
/*
|
|
* Definition of Field-Indexes for stillVisitedNodes-orel
|
|
*/
|
|
static const int
|
|
HL_INDEX_OF_NODE_ID_IN_STILL_VISITED = 0;
|
|
|
|
|
|
/*
|
|
* Processes a h-hop forward search for the given vertex v to be contracted.
|
|
* Does so by iterating over all source nodes s having an incoming
|
|
* edge e(s, v) to v.
|
|
* Takes the given distances from a previously executed one-hop reverse
|
|
* search ( @see copyMultimapReverseSearchXT)
|
|
* for the same vertext v and creates a copy of it for each source node s.
|
|
* Stores shortcuts found during forward search in
|
|
* the given OrderedRelation.
|
|
* Uses a h-hop-size during forward search to abort when looking
|
|
* for shorter pathes
|
|
* than the potentially shortcut currently viewed.
|
|
* The h-hop-size means how deep (in the meaning of network depth)
|
|
* the dijkstra-search shall be performed,
|
|
* started out of the appropriate source node s (having an edge e(s, v)
|
|
* incoming to the current vertex v.
|
|
*
|
|
* @param orelEdgesSource is an OrderedRelation containging all edges
|
|
* of the underlying graph sorted by the field Source
|
|
* @param orelEdgesTarget is an OrderedRelation containging all edges
|
|
* of the underlying graph sorted by the field Target
|
|
* @param multimapReverseSearchXT the Ordered map by reference where
|
|
* all distances found by the reverse search have been stored in
|
|
* @param currentVertexIdFwdV the current vertex v to be contracted
|
|
* @param shortcutsToBeCreatedOrelSourceToBeDeleted the multimap by
|
|
* reference where all shortcuts will be stored in
|
|
* @param hDepth the h-hop-size to be used, will be overwritten
|
|
* by @see HL_DEFAULT_H_DEPTH if value < 1
|
|
* @return true, since the result of this function will be stored
|
|
* directly in @see shortcutsToBeCreatedOrelSourceToBeDeleted
|
|
*
|
|
*/
|
|
bool hlHHopForwardSearch(OrderedRelation*
|
|
orelEdgesSource, OrderedRelation* orelEdgesTarget,
|
|
std::multimap<int, std::tuple<int, double>>
|
|
&multimapReverseSearchXT,
|
|
CcInt* currentVertexIdFwdV,
|
|
std::multimap<int, std::tuple<int, double, int>>
|
|
&shortcutsToBeCreatedOrelSourceToBeDeleted,
|
|
int hDepth) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Starting hlHHopForwardSearch with v = " <<
|
|
currentVertexIdFwdV->GetIntval() <<
|
|
" and hDepth = " << hDepth << endl);
|
|
#endif
|
|
|
|
if(hDepth < 1)
|
|
{
|
|
hDepth = HL_DEFAULT_H_DEPTH;
|
|
}
|
|
|
|
//Prepare Range scan
|
|
//Create From and to by currentVertexID (=v)
|
|
std::vector<void*> vecAttributesFromFwdV(1);
|
|
vecAttributesFromFwdV[0] = currentVertexIdFwdV;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesFromFwdV(1);
|
|
vecAttrTypesFromFwdV[0] =
|
|
currentVertexIdFwdV->getSMIKeyType();
|
|
CompositeKey fromFwdV(vecAttributesFromFwdV,
|
|
vecAttrTypesFromFwdV, false);
|
|
|
|
CcInt currentVertexIdPlusOneFwdV(true,
|
|
currentVertexIdFwdV->GetIntval() + 1);
|
|
CcInt* currentVertexIdPlusOnePtrFwdV =
|
|
¤tVertexIdPlusOneFwdV;
|
|
std::vector<void*> vecAttributesToFwdV(1);
|
|
vecAttributesToFwdV[0] =
|
|
currentVertexIdPlusOnePtrFwdV;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesToFwdV(1);
|
|
vecAttrTypesToFwdV[0] =
|
|
currentVertexIdPlusOnePtrFwdV->getSMIKeyType();
|
|
CompositeKey toFwdV(vecAttributesToFwdV,
|
|
vecAttrTypesToFwdV, false);
|
|
|
|
//get all incoming edges (s, v) to v
|
|
GenericRelationIterator* relEdgesTargetIterSV =
|
|
orelEdgesTarget->MakeRangeScan(fromFwdV, toFwdV);
|
|
//TODO: muss der Wert von currentVertexIdPlusOnePtr->getSMIKeyType();
|
|
// noch gelöscht werden per delete? Wenn ja dann auch andere derartige
|
|
|
|
//Get first Tuple of them
|
|
Tuple* currentEdgeTargetTupleSV =
|
|
relEdgesTargetIterSV->GetNextTuple();
|
|
|
|
//Iterate over all Incoming Tuples s to v
|
|
while(currentEdgeTargetTupleSV)
|
|
{
|
|
//Get ID of current SourceNode (=s)
|
|
CcInt* currentSourceNodeFwdS = (CcInt*)
|
|
currentEdgeTargetTupleSV->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("Process next source node s = " <<
|
|
currentSourceNodeFwdS->GetIntval() << endl);
|
|
#endif
|
|
|
|
//Copy of multimapReverseSearchXT
|
|
std::multimap<int, std::tuple<int, double>>
|
|
copyMultimapReverseSearchXT =
|
|
multimapReverseSearchXT; //XXTODO: ist diese Zuweisung
|
|
// ein Problem in Bezug auf nicht gelöschte Daten der
|
|
// vorherigen Iteration?
|
|
|
|
//delete current surce node s from current copy of reverseSearchXT
|
|
// where s = t
|
|
// because it does not make sense to find/ create a shortcut
|
|
// from s to s.
|
|
// this is posible because s and v can have both, an incoming
|
|
// and an outgoing edge
|
|
//this for-loop has an emtpy increment section since it is
|
|
// incremented manually next to the erase-command
|
|
for (std::multimap<int, std::tuple<int, double>>::iterator
|
|
reverseXTIter =
|
|
copyMultimapReverseSearchXT.begin();
|
|
reverseXTIter !=
|
|
copyMultimapReverseSearchXT.end();)
|
|
{
|
|
// you have to do this because iterators are invalidated
|
|
std::multimap<int, std::tuple<int, double>>::iterator
|
|
currReverseIter = reverseXTIter++;
|
|
|
|
std::tuple<int, double> currReverseTuple =
|
|
(*currReverseIter).second;
|
|
int currentEraseId =
|
|
std::get<HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE -
|
|
1>(currReverseTuple);
|
|
// removes all even values
|
|
if (currentEraseId ==
|
|
currentSourceNodeFwdS->GetIntval())
|
|
{
|
|
copyMultimapReverseSearchXT.erase(
|
|
currReverseIter);
|
|
#ifdef USEDEBUG
|
|
double tmpDist =
|
|
std::get<HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE - 1>
|
|
(currReverseTuple);
|
|
LogDebug("erased s (=t) itself from XT: x=" <<
|
|
(*currReverseIter).first << ", t=" <<
|
|
currentEraseId << " dist: " << tmpDist << endl);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//Check whether there are direct edges to some of the
|
|
// current target-endpoints
|
|
double currDistSX = 0.0;
|
|
double distSV = hlGetWeightedCost(
|
|
HL_DEFAULT_COST_MODE, currentEdgeTargetTupleSV);
|
|
hlForwardSearchCheckForWitnessPath(
|
|
copyMultimapReverseSearchXT,
|
|
currentVertexIdFwdV->GetIntval(),
|
|
currentSourceNodeFwdS->GetIntval(), currDistSX,
|
|
distSV);
|
|
|
|
//Check whether there are vertices to be found left, else go
|
|
// to next loop loop
|
|
if(copyMultimapReverseSearchXT.size() == 0)
|
|
{
|
|
//Free Resources
|
|
currentEdgeTargetTupleSV->DeleteIfAllowed();
|
|
currentEdgeTargetTupleSV = 0;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("all witnesses found continue with next SV edge"
|
|
<< endl);
|
|
#endif
|
|
continue;
|
|
}
|
|
|
|
//Build list containing all still visited nodes during
|
|
// current forward search starting at current s
|
|
std::unordered_set<int> stillVisitedNodesSet;
|
|
stillVisitedNodesSet.insert(
|
|
currentSourceNodeFwdS->GetIntval());
|
|
|
|
//process forward search for current source-tuple s
|
|
hlForwardSearchProcessIncomingEdge(
|
|
orelEdgesSource,
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted,
|
|
currentVertexIdFwdV->GetIntval(),
|
|
currentSourceNodeFwdS, stillVisitedNodesSet,
|
|
copyMultimapReverseSearchXT, hDepth, distSV);
|
|
|
|
//Free Incoming-Iteration
|
|
currentEdgeTargetTupleSV->DeleteIfAllowed();
|
|
currentEdgeTargetTupleSV = 0;
|
|
currentEdgeTargetTupleSV =
|
|
relEdgesTargetIterSV->GetNextTuple();
|
|
|
|
copyMultimapReverseSearchXT.clear();
|
|
}
|
|
delete relEdgesTargetIterSV;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Procession of iteration over all incoming Nodes s to current
|
|
* vertex v to be contracted
|
|
* of current forward search ( @see hlHHopForwardSearch).
|
|
* Does a forward search starting from this current incoming node s.
|
|
* The aim is to find other nodes x during the forward search which
|
|
* exist in copyMultimapReverseSearchXT
|
|
* and for which then there exist a shorter path from s to t via x
|
|
*7than via v.
|
|
* If there exist a shorter path all occurrences of x will be eraised
|
|
*7 from copyMultimapReverseSearchXT.
|
|
* Remaining occurences of t within copyMultimapReverseSearchXT will
|
|
* lead to the creation of a shortcut.
|
|
* These then are stored in shortcutsToBeCreatedOrelSourceToBeDeleted.
|
|
*
|
|
* @param orelEdgesSource is an OrderedRelation containging all edges
|
|
* of the underlying graph sorted by the field Source
|
|
* @param shortcutsToBeCreatedOrelSourceToBeDeleted the multimap by
|
|
* reference where all shortcuts will be stored in
|
|
* @param currentVertexIdFwdV the current vertex v to be contracted
|
|
* @param currentSourceNodeFwdS the current source vertex s
|
|
* @param stillVisitedNodesSet is an unordered_set by reference
|
|
* containging all nodes still visited during forward search
|
|
* @param copyMultimapReverseSearchXT copy of the Ordered map by
|
|
* reference where all distances found by the reverse search have
|
|
* been stored in
|
|
* @param hDepth the h-hop-size to be used, will be overwritten
|
|
* by @see HL_DEFAULT_H_DEPTH if value < 1
|
|
* @param distSV the weighted costs of the edge from curent s to current v
|
|
* @return true, since the result of this function will be stored
|
|
* directly in @see shortcutsToBeCreatedOrelSourceToBeDeleted
|
|
*
|
|
*/
|
|
bool hlForwardSearchProcessIncomingEdge(
|
|
OrderedRelation* orelEdgesSource,
|
|
std::multimap<int, std::tuple<int, double, int>>
|
|
&shortcutsToBeCreatedOrelSourceToBeDeleted,
|
|
int currentVertexIdFwdV,
|
|
CcInt* currentSourceNodeFwdS,
|
|
std::unordered_set<int> &stillVisitedNodesSet,
|
|
std::multimap<int, std::tuple<int, double>>
|
|
©MultimapReverseSearchXT, int hDepth,
|
|
double distSV) const
|
|
{
|
|
//Stack for Dijkstra containing not yet visited nodes
|
|
std::multimap<double, std::tuple<int, int>>
|
|
notYetVisitedNodesMultiMap;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("Do initial" << endl);
|
|
#endif
|
|
hlForwardSearchProcessIncomingEdgeInitialSteps(
|
|
orelEdgesSource, currentVertexIdFwdV,
|
|
currentSourceNodeFwdS, notYetVisitedNodesMultiMap,
|
|
copyMultimapReverseSearchXT, distSV);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("Do iterative" << endl);
|
|
#endif
|
|
hlForwardSearchProcessIncomingEdgeIterativeSteps(
|
|
orelEdgesSource, currentVertexIdFwdV,
|
|
notYetVisitedNodesMultiMap, stillVisitedNodesSet,
|
|
copyMultimapReverseSearchXT, hDepth, distSV);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("Do create shortcuts" << endl);
|
|
#endif
|
|
hlForwardSearchCreateAndAppendShortcuts(
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted,
|
|
copyMultimapReverseSearchXT,
|
|
currentSourceNodeFwdS->GetIntval(),
|
|
currentVertexIdFwdV, distSV);
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Does initial, non-iterative Steps as part of
|
|
* @see hlForwardSearchProcessIncomingEdge.
|
|
* At least initializes the search-stack with all other vertexes w
|
|
* outgoing from s but ignoring current v to be contracted.
|
|
*
|
|
* @param orelEdgesSource is an OrderedRelation containging all edges
|
|
* of the underlying graph sorted by the field Source
|
|
* @param currentVertexIdFwdV the current vertex v to be contracted
|
|
* @param currentSourceNodeFwdS the current source vertex s
|
|
* @param notYetVisitedNodesMultiMap is a Multimap by reference
|
|
* containging all nodes scanned but not yet visited during forward search
|
|
* @param copyMultimapReverseSearchXT copy of the Ordered map by
|
|
* reference where all distances found by the reverse search
|
|
* have been stored in
|
|
* @param distSV the weighted costs of the edge from curent s to current v
|
|
* @return true, since the result of this function is the modification
|
|
* of notYetVisitedNodesMultiMap and copyMultimapReverseSearchXT
|
|
*
|
|
*/
|
|
bool hlForwardSearchProcessIncomingEdgeInitialSteps(
|
|
OrderedRelation* orelEdgesSource,
|
|
int currentVertexIdFwdV,
|
|
CcInt* currentSourceNodeFwdS,
|
|
std::multimap<double, std::tuple<int, int>>
|
|
¬YetVisitedNodesMultiMap,
|
|
std::multimap<int, std::tuple<int, double>>
|
|
©MultimapReverseSearchXT, double distSV) const
|
|
{
|
|
//Prepare Range scan
|
|
//Create From and to by currentSourceNodeFwdS (=s)
|
|
std::vector<void*> vecAttributesFromFwdS(1);
|
|
vecAttributesFromFwdS[0] = currentSourceNodeFwdS;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesFromFwdS(1);
|
|
vecAttrTypesFromFwdS[0] =
|
|
currentSourceNodeFwdS->getSMIKeyType();
|
|
CompositeKey fromFwdS(vecAttributesFromFwdS,
|
|
vecAttrTypesFromFwdS, false);
|
|
|
|
CcInt currentSourceNodePlusOneFwdS(true,
|
|
currentSourceNodeFwdS->GetIntval() + 1);
|
|
CcInt* currentSourceNodePlusOnePtrFwdS =
|
|
¤tSourceNodePlusOneFwdS;
|
|
std::vector<void*> vecAttributesToFwdS(1);
|
|
vecAttributesToFwdS[0] =
|
|
currentSourceNodePlusOnePtrFwdS;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesToFwdS(1);
|
|
vecAttrTypesToFwdS[0] =
|
|
currentSourceNodePlusOnePtrFwdS->getSMIKeyType();
|
|
CompositeKey toFwdS(vecAttributesToFwdS,
|
|
vecAttrTypesToFwdS, false);
|
|
|
|
//get all outgoing edges (s, w) of current sourceNode
|
|
// s to any other node w
|
|
GenericRelationIterator* relEdgesSourceIterFwdSW =
|
|
orelEdgesSource->MakeRangeScan(fromFwdS, toFwdS);
|
|
|
|
//Get first Tuple of them =(s, w)
|
|
Tuple* currentEdgeSourceTupleFwdSW =
|
|
relEdgesSourceIterFwdSW->GetNextTuple();
|
|
|
|
//Iterate over all outgoing Tuples from s
|
|
while(currentEdgeSourceTupleFwdSW)
|
|
{
|
|
//Get ID of current TargetNode (=w)
|
|
CcInt* currentTargetNodeW = (CcInt*)
|
|
currentEdgeSourceTupleFwdSW->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
|
|
//ignore current v to be contracted
|
|
if(currentTargetNodeW->GetIntval() !=
|
|
currentVertexIdFwdV)
|
|
{
|
|
//Check whether there are direct edges to some
|
|
// of the current target-endpoints
|
|
double currDistSW = hlGetWeightedCost(
|
|
HL_DEFAULT_COST_MODE,
|
|
currentEdgeSourceTupleFwdSW);
|
|
//TODO get Distance from currentSourceNode (s) to currentTargetNodeW (w)
|
|
hlForwardSearchCheckForWitnessPath(
|
|
copyMultimapReverseSearchXT, currentVertexIdFwdV,
|
|
currentTargetNodeW->GetIntval(), currDistSW,
|
|
distSV);
|
|
|
|
//Check whether there are vertices to be found left,
|
|
// else abort loop
|
|
if(copyMultimapReverseSearchXT.size() == 0)
|
|
{
|
|
//Free Resources
|
|
currentEdgeSourceTupleFwdSW->DeleteIfAllowed();
|
|
currentEdgeSourceTupleFwdSW = 0;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("all witnesses found, break initial steps"
|
|
<< endl);
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
std::tuple<double, int, int>
|
|
currMinNotYetVisitedNodeTuple = std::make_tuple(
|
|
0.0, currentSourceNodeFwdS->GetIntval(), 0);
|
|
#ifdef USEDEBUG
|
|
LogDebug("forward search initial steps insertOrUpdateInNotYet"
|
|
<< endl);
|
|
#endif
|
|
bool isForward = true;
|
|
bool isHHop = true;
|
|
hlInsertOrUpdateTupleInNotYetVisitedList(
|
|
currentVertexIdFwdV,
|
|
currMinNotYetVisitedNodeTuple,
|
|
currentEdgeSourceTupleFwdSW,
|
|
notYetVisitedNodesMultiMap, isForward,
|
|
isHHop); //TODO: übergeben von 0 als null in ordnung?
|
|
}
|
|
|
|
//Free Outgoing-Iteration
|
|
currentEdgeSourceTupleFwdSW->DeleteIfAllowed();
|
|
currentEdgeSourceTupleFwdSW = 0;
|
|
currentEdgeSourceTupleFwdSW =
|
|
relEdgesSourceIterFwdSW->GetNextTuple();
|
|
}
|
|
delete relEdgesSourceIterFwdSW;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Does iterative Steps as part of @see hlForwardSearchProcessIncomingEdge.
|
|
* At least gets next min vertex w of notYetVisitedNodesOrel
|
|
* and scans next vertices x having an edge e(w, x) outgoing from
|
|
* w to x with respect to the hop depth.
|
|
* If the next vertex to scan is more hops (in the meaning of graph depth)
|
|
* away than the h-hop-size allows,
|
|
* this next vertex will not be scanned.
|
|
*
|
|
* @param orelEdgesSource is an OrderedRelation containging all edges of
|
|
* the underlying graph sorted by the field Source
|
|
* @param currentVertexIdFwdV the current vertex v to be contracted
|
|
* @param notYetVisitedNodesMultiMap is a Multimap by refeerence
|
|
* containging all nodes scanned but not yet visited during forward search
|
|
* @param stillVisitedNodesSet is an unordered_set bx reference
|
|
* containging all nodes still visited during forward search
|
|
* @param copyMultimapReverseSearchXT copy of the Ordered map by
|
|
* reference where all distances found by the reverse search have been
|
|
* stored in
|
|
* @param hDepth the h-hop-size to be used, will be overwritten
|
|
* by @see HL_DEFAULT_H_DEPTH if value < 1
|
|
* @param distSV the weighted costs of the edge from curent s to current v
|
|
* @return true, since the result of this function is the modification
|
|
* of notYetVisitedNodesMultiMap, stillVisitedNodesSet and
|
|
* copyMultimapReverseSearchXT
|
|
*
|
|
*/
|
|
bool hlForwardSearchProcessIncomingEdgeIterativeSteps(
|
|
OrderedRelation* orelEdgesSource,
|
|
int currentVertexIdFwdV,
|
|
std::multimap<double, std::tuple<int, int>>
|
|
¬YetVisitedNodesMultiMap,
|
|
std::unordered_set<int> &stillVisitedNodesSet,
|
|
std::multimap<int, std::tuple<int, double>>
|
|
©MultimapReverseSearchXT, int hDepth,
|
|
double distSV) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("notYetVisitedNodesMultiMap.size(): " <<
|
|
notYetVisitedNodesMultiMap.size() <<
|
|
" copyMultimapReverseSearchXT.size(): " <<
|
|
copyMultimapReverseSearchXT.size() << endl);
|
|
#endif
|
|
//Do forward Dijkstra
|
|
//Abort when either there are no more vertices
|
|
// to scan (with respect to the hop-depth)
|
|
// or when there are no more target-vertices to find
|
|
// (because thei still have been found)
|
|
while(notYetVisitedNodesMultiMap.size() > 0 &&
|
|
copyMultimapReverseSearchXT.size() > 0)
|
|
{
|
|
//get Tuple with min(dist)
|
|
std::multimap<double, std::tuple<int, int>>::iterator
|
|
notYetVisitedNodesMultiMapIter =
|
|
notYetVisitedNodesMultiMap.begin();
|
|
double currMinDist =
|
|
(*notYetVisitedNodesMultiMapIter).first;
|
|
|
|
std::tuple<int, int> currTuple =
|
|
(*notYetVisitedNodesMultiMapIter).second;
|
|
int currMinNodeId =
|
|
std::get<HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED -
|
|
1>(currTuple);
|
|
int currMinHopDepth =
|
|
std::get<HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED
|
|
- 1>(currTuple);
|
|
|
|
//Create auxiliary tuple
|
|
std::tuple<double, int, int>
|
|
currMinNotYetVisitedNodeTuple = std::make_tuple(
|
|
currMinDist, currMinNodeId, currMinHopDepth);
|
|
#ifdef USEDEBUG
|
|
LogDebug("next minW: " << currMinNodeId << " - " <<
|
|
currMinDist << " - " << currMinHopDepth << endl);
|
|
#endif
|
|
|
|
//Remove currMinNotYetVisitedNodeTuple from notYetVisitedNodesOrel
|
|
notYetVisitedNodesMultiMap.erase(
|
|
notYetVisitedNodesMultiMapIter);
|
|
|
|
//Add currMinNotyetVisitedNodeTuple to stillVisitedNodesList
|
|
stillVisitedNodesSet.insert(currMinNodeId);
|
|
|
|
//Scan new vertices reachable (with respect to the hop depth)
|
|
// and either insert them into notYetVisitedNodesOrel
|
|
// or update existing entries when there are shorter pathes
|
|
// TODO: der Code geht davon aus, dass edie kleinstmöglich
|
|
// hHop Größe = 1 ist
|
|
if( currMinHopDepth < hDepth)
|
|
{
|
|
hlForwardSearchIterativeStepsScanNewVertices(
|
|
orelEdgesSource, currentVertexIdFwdV,
|
|
currMinNotYetVisitedNodeTuple,
|
|
notYetVisitedNodesMultiMap, stillVisitedNodesSet,
|
|
copyMultimapReverseSearchXT, distSV);
|
|
}
|
|
}
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish of hlForwardSearchProcessIncomingEdgeIterativeSteps"
|
|
<< endl);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Scans for new vertices x reachable from the current vertex w.
|
|
* Adds new vertices scanned in notYetVisitedNodesMultiMap.
|
|
*
|
|
* @param orelEdgesSource is an OrderedRelation containging all edges
|
|
* of the underlying graph sorted by the field Source
|
|
* @param currentVertexIdFwdV the current vertex v to be contracted
|
|
* @param currMinNotYetVisitedNodeTupleFwdW the current tuple w by
|
|
* reference with minimum distance to the current source node
|
|
* @param notYetVisitedNodesMultiMap is an multi map by reference
|
|
* containging all nodes scanned but not yet visited during forward search
|
|
* @param stillVisitedNodesSet is an unordered_set by reference
|
|
* containging all nodes still visited during forward search
|
|
* @param copyMultimapReverseSearchXT copy of the Ordered map by
|
|
* reference where all distances found by the reverse search have
|
|
* been stored in
|
|
* @param distSV the weighted costs of the edge from curent s to current v
|
|
* @return true, since the result of this function is the modification of
|
|
* notYetVisitedNodesMultiMap and copyMultimapReverseSearchXT
|
|
*
|
|
*/
|
|
bool hlForwardSearchIterativeStepsScanNewVertices(
|
|
OrderedRelation* orelEdgesSource,
|
|
int currentVertexIdFwdV,
|
|
std::tuple<double, int, int>
|
|
&currMinNotYetVisitedNodeTupleFwdW,
|
|
std::multimap<double, std::tuple<int, int>>
|
|
¬YetVisitedNodesMultiMap,
|
|
std::unordered_set<int> &stillVisitedNodesSet,
|
|
std::multimap<int, std::tuple<int, double>>
|
|
©MultimapReverseSearchXT, double distSV) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlForwardSearchIterativeStepsScanNewVertices"
|
|
<< endl);
|
|
#endif
|
|
//Get ID of current SourceNode (=w)
|
|
double currentSourceNodeDistSW =
|
|
std::get<HL_INDEX_OF_DIST_IN_NOT_YET_VISITED>
|
|
(currMinNotYetVisitedNodeTupleFwdW);
|
|
int currentSourceNodeFwdW =
|
|
std::get<HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED>
|
|
(currMinNotYetVisitedNodeTupleFwdW);
|
|
|
|
//iterate over all outgoing edges (w, x) from w
|
|
//Prepare Range scan
|
|
//Create From and to by currentSourceNodeFwdW (=w)
|
|
CcInt currentSourceNodeFwdWCcInt(true,
|
|
currentSourceNodeFwdW);
|
|
CcInt* currentSourceNodePtrFwdW =
|
|
¤tSourceNodeFwdWCcInt;
|
|
std::vector<void*> vecAttributesFromFwdW(1);
|
|
vecAttributesFromFwdW[0] =
|
|
currentSourceNodePtrFwdW;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesFromFwdW(1);
|
|
vecAttrTypesFromFwdW[0] =
|
|
currentSourceNodePtrFwdW->getSMIKeyType();
|
|
CompositeKey fromFwdW(vecAttributesFromFwdW,
|
|
vecAttrTypesFromFwdW, false);
|
|
|
|
CcInt currentSourceNodePlusOneFwdW(true,
|
|
currentSourceNodeFwdW + 1);
|
|
CcInt* currentSourceNodePlusOnePtrFwdW =
|
|
¤tSourceNodePlusOneFwdW;
|
|
std::vector<void*> vecAttributesToFwdW(1);
|
|
vecAttributesToFwdW[0] =
|
|
currentSourceNodePlusOnePtrFwdW;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesToFwdW(1);
|
|
vecAttrTypesToFwdW[0] =
|
|
currentSourceNodePlusOnePtrFwdW->getSMIKeyType();
|
|
CompositeKey toFwdW(vecAttributesToFwdW,
|
|
vecAttrTypesToFwdW, false);
|
|
|
|
//get all outgoing edges (w, x) of current sourceNode w
|
|
GenericRelationIterator* relEdgesSourceIterWX =
|
|
orelEdgesSource->MakeRangeScan(fromFwdW, toFwdW);
|
|
|
|
//Get first Tuple of them
|
|
Tuple* currentEdgeSourceTupleWX =
|
|
relEdgesSourceIterWX->GetNextTuple();
|
|
|
|
//Iterate over all outgoing Tuples (x) from w
|
|
while(currentEdgeSourceTupleWX)
|
|
{
|
|
CcInt* currentTargetNodeX = (CcInt*)
|
|
currentEdgeSourceTupleWX->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
#ifdef USEDEBUG
|
|
LogDebug("next iteration: currentTargetNodeX: " <<
|
|
currentTargetNodeX->GetIntval() << endl);
|
|
#endif
|
|
|
|
//ignore current v to be contracted and also ignore still
|
|
// visited nodes
|
|
if(currentTargetNodeX->GetIntval() !=
|
|
currentVertexIdFwdV &&
|
|
stillVisitedNodesSet.count(
|
|
currentTargetNodeX->GetIntval()) == 0)
|
|
{
|
|
double currDistSX = (double)
|
|
currentSourceNodeDistSW + hlGetWeightedCost(
|
|
HL_DEFAULT_COST_MODE,
|
|
currentEdgeSourceTupleWX); //TODO
|
|
|
|
//Check whether there are direct edges to some of the
|
|
// current target-endpoints
|
|
hlForwardSearchCheckForWitnessPath(
|
|
copyMultimapReverseSearchXT, currentVertexIdFwdV,
|
|
currentTargetNodeX->GetIntval(), currDistSX,
|
|
distSV); //TODO weitere parameter
|
|
//Check whether there are vertices to be found left,
|
|
// else abort loop
|
|
if(copyMultimapReverseSearchXT.size() == 0)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("all witnesses found break scan new vertices"
|
|
" of forward search"
|
|
<< endl);
|
|
#endif
|
|
//Free Resources
|
|
currentEdgeSourceTupleWX->DeleteIfAllowed();
|
|
currentEdgeSourceTupleWX = 0;
|
|
|
|
break;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("forward search scan new vertices"
|
|
" insertOrUpdateInNotYet"
|
|
<< endl);
|
|
#endif
|
|
//Either insert the new scanned X into not visited list
|
|
// or update it if it sill exists and has a shorter path
|
|
// via current w
|
|
bool isForward = true;
|
|
bool isHHop = true;
|
|
hlInsertOrUpdateTupleInNotYetVisitedList(
|
|
currentVertexIdFwdV,
|
|
currMinNotYetVisitedNodeTupleFwdW,
|
|
currentEdgeSourceTupleWX,
|
|
notYetVisitedNodesMultiMap, isForward, isHHop);
|
|
}
|
|
|
|
//Free Outgoing-Iteration
|
|
currentEdgeSourceTupleWX->DeleteIfAllowed();
|
|
currentEdgeSourceTupleWX = 0;
|
|
currentEdgeSourceTupleWX =
|
|
relEdgesSourceIterWX->GetNextTuple();
|
|
}
|
|
|
|
delete relEdgesSourceIterWX;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlForwardSearchIterativeStepsScanNewVertices"
|
|
<< endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Either insert the new scanned vertex x into notYetVisitedList
|
|
* or update it if it sill exists but has a shorter path via current w.
|
|
* If currMinNotYetVisitedNodeTupleFwdW is null then its meant that the
|
|
* current tuple is equal the current starting node s.
|
|
* It processe different then regarding the hop-depth and the distance to
|
|
* the source node (so to itself = 0).
|
|
* If x is going to be inserted or updated e.g. its distance is calculated
|
|
* by the distance of the given vertex w so far
|
|
* and the distance of the also given edge leading to x.
|
|
* All descriptions behave vice versa if isForward = false.
|
|
*
|
|
* @param currentVertexIdFwdV the current vertex v to be contracted
|
|
used to skip iteration if next vertex considered is equeal to v
|
|
can be set to -1 when no skipping shall be used
|
|
* @param currMinNotYetVisitedNodeTupleFwdW the current tuple w with the
|
|
* current minimum distance to the actual source s by reference
|
|
it values are used to create those one for the node x which
|
|
* might be inserted or updaten within notYet
|
|
* @param currentEdgeSourceTupleWX the current edge with source = w
|
|
* ( @see currMinNotYetVisitedNodeTupleFwdW)
|
|
* and target = x where x may be inserted or updated within notYet
|
|
* @param notYetVisitedNodesMultiMap is an multi map by reference
|
|
* containging all nodes scanned but not yet visited during forward search
|
|
* @param isForward is a boolean flag to indicate whether the given
|
|
* edgeOrelTuple is used during a forward or reverse search
|
|
* @return true, since the result of this function is the modification
|
|
* of notYetVisitedNodesMultiMap
|
|
*
|
|
*/
|
|
bool hlInsertOrUpdateTupleInNotYetVisitedList(
|
|
int currentVertexIdFwdV,
|
|
std::tuple<double, int, int>
|
|
&currMinNotYetVisitedNodeTupleFwdW,
|
|
Tuple* currentEdgeSourceTupleWX,
|
|
std::multimap<double, std::tuple<int, int>>
|
|
¬YetVisitedNodesMultiMap, bool isForward,
|
|
bool isHHop) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("doing hlInsertOrUpdateTupleInNotYetVisitedList"
|
|
<< endl);
|
|
#endif
|
|
//Get ID of current TargetNode (=x)
|
|
CcInt* currentTargetNodeX;
|
|
if(isForward)
|
|
{
|
|
currentTargetNodeX = (CcInt*)
|
|
currentEdgeSourceTupleWX->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
}
|
|
else
|
|
{
|
|
currentTargetNodeX = (CcInt*)
|
|
currentEdgeSourceTupleWX->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
}
|
|
|
|
//Ignore if x = v (current Node v to be contracted)
|
|
if(currentVertexIdFwdV !=
|
|
currentTargetNodeX->GetIntval())
|
|
{
|
|
double parentDistSW =
|
|
std::get<HL_INDEX_OF_DIST_IN_NOT_YET_VISITED>
|
|
(currMinNotYetVisitedNodeTupleFwdW);
|
|
int parentNodeId =
|
|
std::get<HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED>
|
|
(currMinNotYetVisitedNodeTupleFwdW);
|
|
int parentHopDepth =
|
|
std::get<HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED>
|
|
(currMinNotYetVisitedNodeTupleFwdW);
|
|
|
|
double currDistSWX = parentDistSW +
|
|
hlGetWeightedCost(HL_DEFAULT_COST_MODE,
|
|
currentEdgeSourceTupleWX);
|
|
int currentHopDepthSX = parentHopDepth + 1;
|
|
|
|
//If the next vertex to be added to notYetVisited List still
|
|
// exists there
|
|
// we have to check whether theres a shorter path to it via
|
|
// current W
|
|
bool insertOrUpdate = true;
|
|
double currDistSX = 0.0;
|
|
|
|
for (std::multimap<double, std::tuple<int, int>>::iterator
|
|
notYetVisitedNodesMultiMapIter =
|
|
notYetVisitedNodesMultiMap.begin();
|
|
notYetVisitedNodesMultiMapIter !=
|
|
notYetVisitedNodesMultiMap.end();
|
|
++notYetVisitedNodesMultiMapIter)
|
|
{
|
|
currDistSX =
|
|
(*notYetVisitedNodesMultiMapIter).first;
|
|
std::tuple<int, int> currMultiMapTuple =
|
|
(*notYetVisitedNodesMultiMapIter).second;
|
|
int currId =
|
|
std::get<HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED -
|
|
1>(currMultiMapTuple);
|
|
|
|
//just get edges (v, t) and skipp edges (x, t)
|
|
if(currId == currentTargetNodeX->GetIntval())
|
|
{
|
|
//check if distance and hopdepth needs to be updated
|
|
// within notyetvisitedlist
|
|
if(currDistSWX < currDistSX)
|
|
{
|
|
//remove old entry for inserting new one (which is
|
|
//like an update)
|
|
#ifdef USEDEBUG
|
|
LogDebug("update: erasing old entry for reinserting"
|
|
<< endl);
|
|
#endif
|
|
notYetVisitedNodesMultiMap.erase(
|
|
notYetVisitedNodesMultiMapIter);
|
|
}
|
|
else
|
|
{
|
|
//Do not insert or update because still existing
|
|
// entry is better
|
|
insertOrUpdate = false;
|
|
}
|
|
//break loop, element was found
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(insertOrUpdate)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("going to insert new element to notYet : "
|
|
<< currentTargetNodeX->GetIntval() << " - " <<
|
|
currDistSWX << endl);
|
|
#endif
|
|
|
|
//during Label creation we need the parentNodeId but not
|
|
// the hopDepth so we reuse the hHop field for this
|
|
int hHopOrParentId = -1;
|
|
if(isHHop)
|
|
{
|
|
hHopOrParentId = currentHopDepthSX;
|
|
}
|
|
else
|
|
{
|
|
hHopOrParentId = parentNodeId;
|
|
}
|
|
std::tuple<int, double> insertTuple =
|
|
std::make_tuple(currentTargetNodeX->GetIntval(),
|
|
hHopOrParentId);
|
|
notYetVisitedNodesMultiMap.insert(
|
|
pair<double, std::tuple<int, int>>(currDistSWX,
|
|
insertTuple));
|
|
}
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlInsertOrUpdateTupleInNotYetVisitedList"
|
|
<< endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Checks for a given vertex x whether a witness-path to endpoints
|
|
* from the previous reverse search can be found.
|
|
* Deletes the endpoints then within the given endpoint-list.
|
|
* A Witness-Path is a shorter path from start node s to target node t
|
|
* than the potential shortcut path from s to t via v
|
|
* (the node to be contracted).
|
|
*
|
|
* @param copyMultimapReverseSearchXT copy of the Ordered map by reference
|
|
* where all distances found by the reverse search have been stored in
|
|
* @param currentContractNodeV the current vertex v to be contracted
|
|
* @param currentSourceNodeWitnessX the current vertex x to be found
|
|
* @param distSX the weighted costs of the edge from curent s to current x
|
|
* @param distSV the weighted costs of the edge from curent s to current v
|
|
* @return true, since the result of this function is the modification of
|
|
* copyMultimapReverseSearchXT
|
|
*
|
|
*/
|
|
bool hlForwardSearchCheckForWitnessPath(
|
|
std::multimap<int, std::tuple<int, double>>
|
|
©MultimapReverseSearchXT,
|
|
int currentContractNodeV,
|
|
int currentSourceNodeWitnessX, double distSX,
|
|
double distSV) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("check for witness start" << endl);
|
|
#endif
|
|
//Vector containing node ids to be deleted from orelXT after
|
|
// finishing full iteration
|
|
std::vector<int> nodesToDeleteVector;
|
|
|
|
//get all outgoing edges (x, t) of current sourceNode x
|
|
std::pair <std::multimap<int, std::tuple<int, double>>::iterator,
|
|
std::multimap<int, std::tuple<int, double>>::iterator>
|
|
revXTRangeBoundsIter;
|
|
revXTRangeBoundsIter =
|
|
copyMultimapReverseSearchXT.equal_range(
|
|
currentSourceNodeWitnessX);
|
|
|
|
for (std::multimap<int, std::tuple<int, double>>::iterator
|
|
revXTRangeIter = revXTRangeBoundsIter.first;
|
|
revXTRangeIter != revXTRangeBoundsIter.second;
|
|
++revXTRangeIter)
|
|
{
|
|
|
|
std::tuple<int, double> currTupleXT =
|
|
(*revXTRangeIter).second;
|
|
int currentEdgeReverseAttributeIdT =
|
|
std::get<HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE -
|
|
1>(currTupleXT);
|
|
double currentEdgeReverseAttributeDistXT =
|
|
std::get<HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE - 1>
|
|
(currTupleXT);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("xt found (x = " <<
|
|
currentSourceNodeWitnessX << ", t = " <<
|
|
currentEdgeReverseAttributeIdT << ")" << endl);
|
|
#endif
|
|
|
|
double distSXT = (double) distSX +
|
|
currentEdgeReverseAttributeDistXT;
|
|
double distSVT = (double) distSV +
|
|
hlForwardSearchGetDistVT(
|
|
copyMultimapReverseSearchXT, currentContractNodeV,
|
|
currentEdgeReverseAttributeIdT);
|
|
|
|
if(distSXT <= distSVT)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("witness found" << endl);
|
|
#endif
|
|
//Witnesspath found, remove all Tuples with target = t
|
|
// from current WitnessList (= copyMultimapReverseSearchXT)
|
|
//Build list containing all nodes to be deleted later after
|
|
// iteration has finished
|
|
nodesToDeleteVector.push_back(
|
|
currentEdgeReverseAttributeIdT);
|
|
}
|
|
}
|
|
|
|
for(std::vector<int>::iterator vecIter =
|
|
nodesToDeleteVector.begin();
|
|
vecIter != nodesToDeleteVector.end(); ++vecIter)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("going to erase from XT: " << *vecIter <<
|
|
endl);
|
|
#endif
|
|
//emtpy increment section since its incremented manually
|
|
// next to the erase-command
|
|
for (std::multimap<int, std::tuple<int, double>>::iterator
|
|
reverseXTIter =
|
|
copyMultimapReverseSearchXT.begin();
|
|
reverseXTIter !=
|
|
copyMultimapReverseSearchXT.end();)
|
|
{
|
|
// you have to do this because iterators are invalidated
|
|
std::multimap<int, std::tuple<int, double>>::iterator
|
|
currReverseIter = reverseXTIter++;
|
|
|
|
std::tuple<int, double> currReverseTuple =
|
|
(*currReverseIter).second;
|
|
int currentEraseId =
|
|
std::get<HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE -
|
|
1>(currReverseTuple);
|
|
// removes all even values
|
|
if (currentEraseId == *vecIter)
|
|
{
|
|
copyMultimapReverseSearchXT.erase(
|
|
currReverseIter);
|
|
#ifdef USEDEBUG
|
|
LogDebug("erased witness from XT x= " <<
|
|
(*currReverseIter).first << " t = " <<
|
|
currentEraseId << endl);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish check for witness" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Deletes every tuple from the given orel containing the given
|
|
* nodeId at the given index position.
|
|
*
|
|
* @param currentOrel the OrderedRelation where all tuples found by
|
|
* the search will be deleted
|
|
* @param givenNodeId the Node ID of the vertex t to bedeleted
|
|
* @param index the index position ath which the ID field should be found
|
|
* @return true, since the result of this function is the modification
|
|
* of currentOrel
|
|
*
|
|
*/
|
|
bool hlRemoveTuplesFromOrel(OrderedRelation*
|
|
currentOrel, int givenNodeId, int index) const
|
|
{
|
|
//iterate over all edges (x, t)
|
|
|
|
//get all edges (x, t)
|
|
GenericRelationIterator* currentOrelIter =
|
|
currentOrel->MakeScan(); //TODO: hier werden nur die tuples mit
|
|
// target = t benötigt, die OREL ist aber nach Source (x) sortiert,
|
|
// daher kompletter scan, ggf. auch filter möglich oder wäre der
|
|
// auch nicht schneller weil auch nur iteration?
|
|
|
|
//Get first Tuple of them
|
|
Tuple* currentTuple =
|
|
currentOrelIter->GetNextTuple(); //TODO weil hier nun ein make
|
|
// scan verwendet werden muss, um tuples nach ihrem Target zu
|
|
// finden, entsteht hier zeitgleich lesender und schreibender
|
|
// Zugriff, wie anders gestalten?
|
|
//TODO ggf. die zuvor ausgeführte vectorenliste mit den tuple objekten
|
|
// statt den ids füllen und beim durchlaufen des vectors diese tuples
|
|
// dann direkt löschen?
|
|
//TODO: problem dann: nicht ALLE mit target = t werden dann gefunden,
|
|
// sondern nur die einzelnen
|
|
//TODO: ggf. dann hier aus der iterationalle tuples in einen array
|
|
// schreiben, und nach dem make scan erst erneut iterieren zum
|
|
// direkten löschen?
|
|
|
|
//Iterate over all outgoing Tuples (x, t) from x
|
|
while(currentTuple)
|
|
{
|
|
CcInt* currentNodeId = (CcInt*)
|
|
currentTuple->GetAttribute(index);
|
|
|
|
//remove all tuples incoming to t because witness path
|
|
// has been found
|
|
if(currentNodeId->GetIntval() == givenNodeId)
|
|
{
|
|
currentOrel->DeleteTuple(currentTuple, true);
|
|
}
|
|
|
|
//Free Iteration
|
|
currentTuple->DeleteIfAllowed();
|
|
currentTuple = 0;
|
|
currentTuple = currentOrelIter->GetNextTuple();
|
|
}
|
|
|
|
delete currentOrelIter;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Gets the Distance between the given curent node v to be contracted
|
|
* and the given current target node t by extracting it from the given
|
|
* orel created by the reverse search.
|
|
*
|
|
* @param copyMultimapReverseSearchXT copy of the OrderedRelation where
|
|
* all distances found by the reverse search have been stored in
|
|
* @param currentContractNodeV the Node ID of the vertex t to contracted
|
|
* @param currentTargetNodeWitnessT the Node ID of the vertex t to bedeleted
|
|
* @return true, since the result of this function is the modification of
|
|
* copyMultimapReverseSearchXT
|
|
*
|
|
*/
|
|
double hlForwardSearchGetDistVT(
|
|
std::multimap<int, std::tuple<int, double>>
|
|
©MultimapReverseSearchXT,
|
|
int currentContractNodeV,
|
|
int currentTargetNodeWitnessT) const
|
|
{
|
|
double retVal = -1;
|
|
|
|
std::pair <std::multimap<int, std::tuple<int, double>>::iterator,
|
|
std::multimap<int, std::tuple<int, double>>::iterator>
|
|
revXTRangeBoundsIter;
|
|
revXTRangeBoundsIter =
|
|
copyMultimapReverseSearchXT.equal_range(
|
|
currentContractNodeV);
|
|
|
|
for (std::multimap<int, std::tuple<int, double>>::iterator
|
|
revXTRangeIter = revXTRangeBoundsIter.first;
|
|
revXTRangeIter != revXTRangeBoundsIter.second;
|
|
++revXTRangeIter)
|
|
{
|
|
std::tuple<int, double> currTupleXT =
|
|
(*revXTRangeIter).second;
|
|
int currentEdgeSourceAttributeT =
|
|
std::get<HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE -
|
|
1>(currTupleXT);
|
|
|
|
if(currentEdgeSourceAttributeT ==
|
|
currentTargetNodeWitnessT)
|
|
{
|
|
retVal = std::get<HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE
|
|
- 1>(currTupleXT);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
/*
|
|
* Creates an shortcut for every entry of the given second multimap and
|
|
* appends it to the first given orel
|
|
*
|
|
* @param shortcutsToBeCreatedOrelSourceToBeDeleted the multimap by
|
|
* reference containing all shortcuts to be added to the original
|
|
* edges OrderedRelations
|
|
* @param copyMultimapReverseSearchXT copy of the Ordered multimap by
|
|
* reference where all distances found by the reverse search have been
|
|
* stored in
|
|
* @param currentSourceNodeS the Node ID of the source node s
|
|
* @param currentContractNodeV the Node ID of the vertex t to contracted
|
|
* @param distSV the weighted costs of the edge from curent s to current v
|
|
* @return true, since the result of this function is the modification of
|
|
* shortcutsToBeCreatedOrelSourceToBeDeleted
|
|
*
|
|
*/
|
|
bool hlForwardSearchCreateAndAppendShortcuts(
|
|
std::multimap<int, std::tuple<int, double, int>>
|
|
&shortcutsToBeCreatedOrelSourceToBeDeleted,
|
|
std::multimap<int, std::tuple<int, double>>
|
|
©MultimapReverseSearchXT,
|
|
int currentSourceNodeS, int currentContractNodeV,
|
|
double distSV) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlForwardSearchCreateAndAppendShortcuts"
|
|
<< endl);
|
|
#endif
|
|
//Iterate over all Tuples (x, t) where x = v
|
|
std::pair <std::multimap<int, std::tuple<int, double>>::iterator,
|
|
std::multimap<int, std::tuple<int, double>>::iterator>
|
|
revXTRangeBoundsIter;
|
|
revXTRangeBoundsIter =
|
|
copyMultimapReverseSearchXT.equal_range(
|
|
currentContractNodeV);
|
|
for (std::multimap<int, std::tuple<int, double>>::iterator
|
|
reverseXTMultimapIter =
|
|
revXTRangeBoundsIter.first;
|
|
reverseXTMultimapIter !=
|
|
revXTRangeBoundsIter.second;
|
|
++reverseXTMultimapIter)
|
|
{
|
|
std::tuple<int, double> currTuple =
|
|
(*reverseXTMultimapIter).second;
|
|
/*int currentEdgeSourceIDX =
|
|
(*reverseXTMultimapIter).first;
|
|
*/
|
|
int currentEdgeSourceIDT =
|
|
std::get<HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE -
|
|
1>(currTuple);
|
|
double currentEdgeSourceDistVT =
|
|
std::get<HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE - 1>
|
|
(currTuple);
|
|
|
|
//create shortcut and add to
|
|
// shortcutsToBeCreatedOrelSourceToBeDeleted
|
|
#ifdef USEDEBUG
|
|
LogDebug("insert new shortcut to multimap (" <<
|
|
currentSourceNodeS << ", " << currentEdgeSourceIDT
|
|
<< ", " << distSV + currentEdgeSourceDistVT <<
|
|
")"<< endl);
|
|
#endif
|
|
std::tuple<int, double, int> insertTuple =
|
|
std::make_tuple(currentEdgeSourceIDT,
|
|
distSV + currentEdgeSourceDistVT,
|
|
currentContractNodeV);
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted.insert(
|
|
pair<int, std::tuple<int, double, int>>
|
|
(currentSourceNodeS, insertTuple));
|
|
}
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlForwardSearchCreateAndAppendShortcuts"
|
|
<< endl);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Definition of Field-Indexes for ranked nodes-orel
|
|
*/
|
|
static const int HL_INDEX_OF_ID_IN_NODES_RANKED =
|
|
2;
|
|
static const int HL_INDEX_OF_RANK_IN_NODES_RANKED
|
|
= 4;
|
|
|
|
/*
|
|
* Iterates over all nodes of the given Orel nodesWithRankOrelRank
|
|
* which is expected to be sorted by Rank.
|
|
* These nodes will be contracted in their particular iteration.
|
|
* Creates a copy of the orels edgesWithViaOrelSource and
|
|
* edgesWithViaOrelTarget (outside the following loop).
|
|
* Calls for each iteration hlDoContraction which returns the
|
|
* shortcuts to be created.
|
|
* Adds the shortcuts to be created to the copies of the Orels
|
|
* edgesWithViaOrelTarget and edgesWithViaOrelSource
|
|
* (inside the particular iteration).
|
|
* Adds the same shortcuts to be created to the original Orels
|
|
* edgesWithViaOrelSource and edgesWithViaOrelTarget.
|
|
* Removes all Edges leading to or coming from the current node to be
|
|
* contracted
|
|
* within the copies of edgesWithViaOrelSource and edgesWithViaOrelTarget.
|
|
*
|
|
* @param nodesWithRankOrelRank is an OrderedRelation containging all
|
|
* nodes of the underlying graph sorted by the field Rank
|
|
* @param edgesWithViaOrelSource is an OrderedRelation containging all
|
|
* edges of the underlying graph sorted by the field Source
|
|
* @param edgesWithViaOrelTarget is an OrderedRelation containging all
|
|
* edges of the underlying graph sorted by the field Target
|
|
* @param hHop the h-hop-size to be used, will be overwritten
|
|
* by @see HL_DEFAULT_H_DEPTH if value < 1
|
|
* @return true, since the result of this function is the modification
|
|
* of edgesWithViaOrelSource and edgesWithViaOrelTarget
|
|
*/
|
|
bool hlIterateOverAllNodesByRankAscAndDoContraction(
|
|
OrderedRelation* nodesWithRankOrelRank,
|
|
OrderedRelation* edgesWithViaOrelSource,
|
|
OrderedRelation* edgesWithViaOrelTarget,
|
|
int hHop) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlIterateOverAllNodesByRankAscAndDoContraction"
|
|
<< endl);
|
|
#endif
|
|
//Copy of edgesWithViaOrelSource
|
|
ListExpr relTypeSource;
|
|
nl->ReadFromString(hlGetEdgesOrelSourceTypeInfo(),
|
|
relTypeSource);
|
|
ListExpr relNumTypeSource =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
relTypeSource);
|
|
Word wrelSource;
|
|
wrelSource.setAddr(edgesWithViaOrelSource);
|
|
Word wrelSource2 = edgesWithViaOrelSource->Clone(
|
|
relNumTypeSource, wrelSource);
|
|
OrderedRelation* copyEdgesWithViaOrelSource =
|
|
(OrderedRelation*) wrelSource2.addr;
|
|
//TODO: die geklonte rel muss aber noch wie unten gelöscht werden oder?
|
|
//TODO: der numtype, kann der auch aus der orel ausgelesen werden?
|
|
//TODO: ggf. muss der Klon noch gelöscht werden per Delete?
|
|
#ifdef USEDEBUG
|
|
LogDebug("edgesWithViaOrelSource cloned" << endl);
|
|
#endif
|
|
|
|
//Copy of edgesWithViaOrelTarget
|
|
ListExpr relTypeTarget;
|
|
nl->ReadFromString(hlGetEdgesOrelTargetTypeInfo(),
|
|
relTypeTarget);
|
|
ListExpr relNumTypeTarget =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
relTypeTarget);
|
|
Word wrelTarget;
|
|
wrelTarget.setAddr(edgesWithViaOrelTarget);
|
|
Word wrelTarget2 = edgesWithViaOrelTarget->Clone(
|
|
relNumTypeTarget, wrelTarget);
|
|
OrderedRelation* copyEdgesWithViaOrelTarget =
|
|
(OrderedRelation*) wrelTarget2.addr;
|
|
//TODO: die geklonte rel muss aber noch wie unten gelöscht werden oder?
|
|
//TODO: der numtype, kann der auch aus der orel ausgelesen werden?
|
|
//TODO: ggf. muss der Klon noch gelöscht werden per Delete?
|
|
#ifdef USEDEBUG
|
|
LogDebug("edgesWithViaOrelTarget cloned" << endl);
|
|
#endif
|
|
|
|
std::multimap<int, std::tuple<int, double, int>>
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted;
|
|
|
|
//Iterate Over all Ranked Nodes in ascending order of their rank
|
|
GenericRelationIterator* nodesWithRankOrelRankIter
|
|
= nodesWithRankOrelRank->MakeScan();
|
|
Tuple* currentNodeRanked =
|
|
nodesWithRankOrelRankIter->GetNextTuple();
|
|
#ifdef USEDEBUG
|
|
LogDebug("iterate over all nodes by rank" << endl);
|
|
#endif
|
|
|
|
#ifdef USEDEBUG
|
|
int countProgress = 0;
|
|
#endif
|
|
while(currentNodeRanked)
|
|
{
|
|
CcInt* currentNodeRankedId = (CcInt*)
|
|
currentNodeRanked->GetAttribute(HL_INDEX_OF_ID_IN_NODES_RANKED);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("do Contraction for: " <<
|
|
currentNodeRankedId->GetIntval() << " (" <<
|
|
++countProgress << "/" <<
|
|
nodesWithRankOrelRank->GetNoTuples() << ")" <<
|
|
endl);
|
|
#endif
|
|
|
|
hlDoContraction(copyEdgesWithViaOrelSource,
|
|
copyEdgesWithViaOrelTarget,
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted,
|
|
currentNodeRankedId, hHop);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("remove edges to and from current v in copy edges relation"
|
|
<< endl);
|
|
#endif
|
|
hlRemoveContractedEdgesFromEdgesRelations(
|
|
copyEdgesWithViaOrelSource,
|
|
copyEdgesWithViaOrelTarget, currentNodeRankedId);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("remove existing edges parallel to new"
|
|
" shortcuts to be created"
|
|
<< endl);
|
|
#endif
|
|
hlRemoveParallelEdgesFromEdgesRelations(
|
|
copyEdgesWithViaOrelSource,
|
|
copyEdgesWithViaOrelTarget,
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("remove existing original edges parallel to"
|
|
" new shortcuts to be created"
|
|
<< endl);
|
|
#endif
|
|
hlRemoveParallelEdgesFromEdgesRelations(
|
|
edgesWithViaOrelSource, edgesWithViaOrelTarget,
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("add shortcuts to copy edges relations" <<
|
|
endl);
|
|
#endif
|
|
//Add Shortcuts to Edges Relations
|
|
hlAddShortcutsToEdgesRelations(
|
|
copyEdgesWithViaOrelSource,
|
|
copyEdgesWithViaOrelTarget,
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("add shortcuts to original edges relations"
|
|
<< endl);
|
|
#endif
|
|
//Add Shortcuts to Edges Relations
|
|
hlAddShortcutsToEdgesRelations(
|
|
edgesWithViaOrelSource, edgesWithViaOrelTarget,
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted);
|
|
|
|
//Free Outgoing-Iteration
|
|
currentNodeRanked->DeleteIfAllowed();
|
|
currentNodeRanked = 0;
|
|
currentNodeRanked =
|
|
nodesWithRankOrelRankIter->GetNextTuple();
|
|
|
|
//clear shortcuts multimap for next run
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted.clear();
|
|
|
|
}
|
|
#ifdef USEDEBUG
|
|
LogDebug("finished iteration" << endl);
|
|
#endif
|
|
|
|
//Free Resources
|
|
delete nodesWithRankOrelRankIter; //TODO: richtig, dass der
|
|
// iter nur deleted wird ohne besondere funktion?
|
|
OrderedRelation::Delete(relNumTypeSource,
|
|
wrelSource2);
|
|
OrderedRelation::Delete(relNumTypeTarget,
|
|
wrelTarget2);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlIterateOverAllNodesByRankAscAndDoContraction"
|
|
<< endl);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Contract the given node by running a oneHopReverse-Search
|
|
* and a hHopForwardSearch.
|
|
*
|
|
* @param edgesWithViaOrelSource is an OrderedRelation containging all
|
|
* edges of the underlying graph sorted by the field Source
|
|
* @param edgesWithViaOrelTarget is an OrderedRelation containging all
|
|
* edges of the underlying graph sorted by the field Target
|
|
* @param shortcutsToBeCreatedOrelSourceToBeDeleted is a Multimap by
|
|
* reference containging all shortcuts to be added to the original edges
|
|
* OrderedRelations
|
|
* @param currentVToBeContracted the Node ID of the vertex t to contracted
|
|
* @param hHop the h-hop-size to be used, will be overwritten
|
|
* by @see HL_DEFAULT_H_DEPTH if value < 1
|
|
* @return true, since the result of this function is the modification
|
|
* of shortcutsToBeCreatedOrelSourceToBeDeleted
|
|
*/
|
|
bool hlDoContraction(OrderedRelation*
|
|
edgesWithViaOrelSource,
|
|
OrderedRelation* edgesWithViaOrelTarget,
|
|
std::multimap<int, std::tuple<int, double, int>>
|
|
&shortcutsToBeCreatedOrelSourceToBeDeleted,
|
|
CcInt* currentVToBeContracted, int hHop) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlDoContraction" << endl);
|
|
#endif
|
|
|
|
//Reverse search
|
|
std::multimap<int, std::tuple<int, double>>
|
|
oneHopReverseMultiMap; //XXTODO: ist diese zuweisung ein
|
|
// Problem in Bezug auf Daten aus vorherigen Iterationen?
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("do hlOneHopReverseSearch" << endl);
|
|
#endif
|
|
hlOneHopReverseSearch(edgesWithViaOrelSource,
|
|
edgesWithViaOrelTarget, currentVToBeContracted,
|
|
oneHopReverseMultiMap);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("do hlHHopForwardSearch" << endl);
|
|
#endif
|
|
hlHHopForwardSearch(edgesWithViaOrelSource,
|
|
edgesWithViaOrelTarget, oneHopReverseMultiMap,
|
|
currentVToBeContracted,
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted, hHop);
|
|
|
|
oneHopReverseMultiMap.clear();
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlDoContraction" << endl);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Adds all shortcuts from shortcutsToBeCreatedOrelSourceToBeDeleted to
|
|
* the original edges OrderedRelations
|
|
* edgesWithViaOrelSource and edgesWithViaOrelTarget
|
|
*
|
|
* @param edgesWithViaOrelSource is an OrderedRelation containging all
|
|
* edges of the underlying graph sorted by the field Source
|
|
* @param edgesWithViaOrelTarget is an OrderedRelation containging all
|
|
* edges of the underlying graph sorted by the field Target
|
|
* @param shortcutsToBeCreatedOrelSourceToBeDeleted is a Multimap by
|
|
* reference containging all shortcuts to be added to the original edges
|
|
* OrderedRelations
|
|
* @return true, since the result of this function is the modification of
|
|
* edgesWithViaOrelSource and edgesWithViaOrelTarget
|
|
*/
|
|
bool hlAddShortcutsToEdgesRelations(
|
|
OrderedRelation* edgesWithViaOrelSource,
|
|
OrderedRelation* edgesWithViaOrelTarget,
|
|
std::multimap<int, std::tuple<int, double, int>>
|
|
&shortcutsToBeCreatedOrelSourceToBeDeleted) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlAddShortcutsToEdgesRelations" <<
|
|
endl);
|
|
#endif
|
|
|
|
for (std::multimap<int, std::tuple<int, double, int>>::iterator
|
|
shortcutsIter =
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted.begin();
|
|
shortcutsIter !=
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted.end();
|
|
++shortcutsIter)
|
|
{
|
|
std::tuple<int, double, int> currTuple =
|
|
(*shortcutsIter).second;
|
|
|
|
int currentSource = (*shortcutsIter).first;
|
|
int currentTarget =
|
|
std::get<HL_INDEX_OF_TARGET_IN_SHORTCUT_TUPLE -
|
|
1>(currTuple);
|
|
int currentParent =
|
|
std::get<HL_INDEX_OF_PARENT_ID_IN_SHORTCUT_TUPLE -
|
|
1>(currTuple);
|
|
double currentCosts =
|
|
std::get<HL_INDEX_OF_DIST_IN_SHORTCUT_TUPLE - 1>
|
|
(currTuple);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("build next inputtuple (" << currentSource
|
|
<< ", " << currentTarget << ")" << endl);
|
|
#endif
|
|
|
|
ListExpr relTypeSource;
|
|
nl->ReadFromString(hlGetEdgesOrelSourceTypeInfo(), relTypeSource);
|
|
ListExpr tupleNumTypeSource =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relTypeSource));
|
|
Tuple* insertTuple = new Tuple(
|
|
tupleNumTypeSource);
|
|
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE, new CcInt(true,
|
|
currentSource));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE, new CcInt(true,
|
|
currentTarget));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_SOURCE_POS_IN_EDGE_TUPLE,
|
|
new Point(false, 0.0, 0.0));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_TARGET_POS_IN_EDGE_TUPLE,
|
|
new Point(false, 0.0, 0.0));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_SOURCE_NODE_COUNTER_IN_EDGE_TUPLE,
|
|
new CcInt(false));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_TARGET_NODE_COUNTER_IN_EDGE_TUPLE,
|
|
new CcInt(false));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_CURVE_IN_EDGE_TUPLE,
|
|
new SimpleLine(0));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_ROAD_NAME_IN_EDGE_TUPLE,
|
|
new FText(false));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_ROAD_TYPE_IN_EDGE_TUPLE,
|
|
new FText(false));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_WAY_ID_IN_EDGE_TUPLE,
|
|
new LongInt(false));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_COSTS_IN_EDGE_TUPLE, new CcReal(true,
|
|
currentCosts));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_PARENT_ID_IN_EDGE_TUPLE,
|
|
new CcInt(true, currentParent));
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("append to edgesWithViaOrelSource" << endl);
|
|
#endif
|
|
edgesWithViaOrelSource->AppendTuple(insertTuple);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("append to edgesWithViaOrelTarget" << endl);
|
|
#endif
|
|
edgesWithViaOrelTarget->AppendTuple(insertTuple);
|
|
|
|
insertTuple->DeleteIfAllowed(); //TODO zu früh gelöscht weil orel
|
|
// wo es appended wurde noch verwendet wird?
|
|
insertTuple = 0;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get next tuple" << endl);
|
|
#endif
|
|
//Free Outgoing-Iteration
|
|
}
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish iteration" << endl);
|
|
#endif
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("end hlAddShortcutsToEdgesRelations" <<
|
|
endl);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Removes all incoming and outgoing edges to and from the given node
|
|
* v within the given edges orels which are the current temporal
|
|
* copies (currentEdgesOrelSource and currentEdgesOrelTarget)
|
|
*
|
|
* @param currentEdgesOrelSource is an OrderedRelation containging all
|
|
* remaining edges of the underlying graph sorted by the field Source
|
|
* @param currentEdgesOrelTarget is an OrderedRelation containging all
|
|
* remaining edges of the underlying graph sorted by the field Target
|
|
* @param currentContractedV the current node v which has been contracted
|
|
* and for which its incoming and outgoing edges
|
|
* shall be deleted within the given edgesOrels Source and Target
|
|
* @return true, since the result of this function is the modification of
|
|
* currentEdgesOrelSource and currentEdgesOrelTarget
|
|
*/
|
|
bool hlRemoveContractedEdgesFromEdgesRelations(
|
|
OrderedRelation* currentEdgesOrelSource,
|
|
OrderedRelation* currentEdgesOrelTarget,
|
|
CcInt* currentContractedV) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlRemoveContractedEdgesFromEdgesRelations"
|
|
<< endl);
|
|
#endif
|
|
|
|
//Prepare Range scan
|
|
//Create From and to by currentVertexID (=v)
|
|
std::vector<void*> vecAttributesFromFwdV(1);
|
|
vecAttributesFromFwdV[0] = currentContractedV;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesFromFwdV(1);
|
|
vecAttrTypesFromFwdV[0] =
|
|
currentContractedV->getSMIKeyType();
|
|
CompositeKey fromFwdV(vecAttributesFromFwdV,
|
|
vecAttrTypesFromFwdV, false);
|
|
|
|
CcInt currentContractedVPlusOneFwdV(
|
|
true, currentContractedV->GetIntval() + 1);
|
|
CcInt* currentVertexIdPlusOnePtrFwdV =
|
|
¤tContractedVPlusOneFwdV;
|
|
std::vector<void*> vecAttributesToFwdV(1);
|
|
vecAttributesToFwdV[0] =
|
|
currentVertexIdPlusOnePtrFwdV;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesToFwdV(1);
|
|
vecAttrTypesToFwdV[0] =
|
|
currentVertexIdPlusOnePtrFwdV->getSMIKeyType();
|
|
CompositeKey toFwdV(vecAttributesToFwdV, vecAttrTypesToFwdV, false);
|
|
|
|
|
|
vector<Tuple*> tupleVectorToDeleteSource;
|
|
vector<Tuple*> tupleVectorToDeleteTarget;
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("remove incoming edges SV" <<
|
|
endl);
|
|
#endif //XXTODO: in orelTarget müssten aber auch die
|
|
// ausgehenden Kanten gelöscht werden, dafür wäre aber
|
|
// ein full scan notwendig?!
|
|
GenericRelationIterator* relEdgesTargetIterSV =
|
|
currentEdgesOrelTarget->MakeRangeScan(fromFwdV,
|
|
toFwdV);
|
|
Tuple* currentEdgeTargetTupleSV =
|
|
relEdgesTargetIterSV->GetNextTuple();
|
|
while(currentEdgeTargetTupleSV)
|
|
{
|
|
//Get SourceNode of current edge
|
|
CcInt* currentEdgeTargetTupleSVSourceId =
|
|
(CcInt*) currentEdgeTargetTupleSV->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
|
|
#ifdef USEDEBUG
|
|
CcInt* currentEdgeTargetTupleSVTargetId =
|
|
(CcInt*) currentEdgeTargetTupleSV->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
|
|
LogDebug("going to delete: (" <<
|
|
currentEdgeTargetTupleSVSourceId->GetIntval() <<
|
|
"," << currentEdgeTargetTupleSVTargetId->GetIntval()
|
|
<< ")" << endl);
|
|
#endif
|
|
//Add tuple to vector
|
|
tupleVectorToDeleteTarget.push_back(
|
|
currentEdgeTargetTupleSV);
|
|
|
|
//Add tuple to opposite vector
|
|
hlRemoveContractedEdgesFromEdgesRelationsScanOppositeOrel(
|
|
currentEdgesOrelSource,
|
|
currentContractedV->GetIntval(),
|
|
currentEdgeTargetTupleSVSourceId,
|
|
tupleVectorToDeleteSource, true);
|
|
|
|
//dont delete Pointers, we need them later
|
|
currentEdgeTargetTupleSV = 0;
|
|
currentEdgeTargetTupleSV =
|
|
relEdgesTargetIterSV->GetNextTuple();
|
|
}
|
|
delete relEdgesTargetIterSV;
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("remove outgoing edges VT" <<
|
|
endl);
|
|
#endif //XXTOTO: auch eingehende Kanten sollten gelöscht werden?!
|
|
GenericRelationIterator* relEdgesSourceIterVT =
|
|
currentEdgesOrelSource->MakeRangeScan(fromFwdV,
|
|
toFwdV);
|
|
Tuple* currentEdgeSourceTupleVT =
|
|
relEdgesSourceIterVT->GetNextTuple();
|
|
while(currentEdgeSourceTupleVT)
|
|
{
|
|
//Get SourceNode of current edge
|
|
CcInt* currentEdgeSourceTupleVTTargetId =
|
|
(CcInt*) currentEdgeSourceTupleVT->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
|
|
#ifdef USEDEBUG
|
|
CcInt* currentEdgeSourceTupleVTSourceId =
|
|
(CcInt*) currentEdgeSourceTupleVT->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
|
|
LogDebug("going to delete: (" <<
|
|
currentEdgeSourceTupleVTSourceId->GetIntval() <<
|
|
"," << currentEdgeSourceTupleVTTargetId->GetIntval()
|
|
<< ")" << endl);
|
|
#endif
|
|
//Add tuple to vector
|
|
tupleVectorToDeleteSource.push_back(
|
|
currentEdgeSourceTupleVT);
|
|
|
|
//Add tuple to opposite vector
|
|
hlRemoveContractedEdgesFromEdgesRelationsScanOppositeOrel(
|
|
currentEdgesOrelTarget,
|
|
currentContractedV->GetIntval(),
|
|
currentEdgeSourceTupleVTTargetId,
|
|
tupleVectorToDeleteTarget, false);
|
|
|
|
//dont delete Pointers, we need them later
|
|
currentEdgeSourceTupleVT = 0;
|
|
currentEdgeSourceTupleVT =
|
|
relEdgesSourceIterVT->GetNextTuple();
|
|
}
|
|
delete relEdgesSourceIterVT;
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("iterate tupleVectorToDeleteTarget" <<
|
|
endl);
|
|
#endif
|
|
for (std::vector<Tuple*>::iterator
|
|
currVectorTargetIter =
|
|
tupleVectorToDeleteTarget.begin();
|
|
currVectorTargetIter !=
|
|
tupleVectorToDeleteTarget.end();
|
|
++currVectorTargetIter)
|
|
{
|
|
Tuple* tmpTuple = *(currVectorTargetIter);
|
|
|
|
if(tmpTuple)
|
|
{
|
|
currentEdgesOrelTarget->DeleteTuple(tmpTuple,
|
|
true); //XXTODO: geht das?
|
|
tmpTuple->DeleteIfAllowed();
|
|
tmpTuple = 0;
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("iterate tupleVectorToDeleteSource" <<
|
|
endl);
|
|
#endif
|
|
for (std::vector<Tuple*>::iterator
|
|
currVectorSourceIter =
|
|
tupleVectorToDeleteSource.begin();
|
|
currVectorSourceIter !=
|
|
tupleVectorToDeleteSource.end();
|
|
++currVectorSourceIter)
|
|
{
|
|
Tuple* tmpTuple2 = *(currVectorSourceIter);
|
|
|
|
currentEdgesOrelSource->DeleteTuple(tmpTuple2,
|
|
true); //XXTODO: geht das?
|
|
tmpTuple2->DeleteIfAllowed();
|
|
tmpTuple2 = 0;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("end hlRemoveContractedEdgesFromEdgesRelations"
|
|
<< endl);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Searches for still existing edges (s, t) within the given
|
|
* OrderedReation currentEdgesOrelSource and currentEdgesOrelTarget
|
|
* which run parallel to a shortcut to be added to the same
|
|
* OrderedRelations.
|
|
*
|
|
* @param currentEdgesOrelSource is an OrderedRelation containging all
|
|
* remaining edges of the underlying graph sorted by the field Source
|
|
* @param currentEdgesOrelTarget is an OrderedRelation containging all
|
|
* remaining edges of the underlying graph sorted by the field Target
|
|
* @param shortcutsToBeCreatedOrelSourceToBeDeleted the shortcuts to be
|
|
* added to the orderedRelations
|
|
* @return true, since the result of this function is the modification
|
|
* of currentEdgesOrelSource and currentEdgesOrelTarget
|
|
*/
|
|
bool hlRemoveParallelEdgesFromEdgesRelations(
|
|
OrderedRelation* currentEdgesOrelSource,
|
|
OrderedRelation* currentEdgesOrelTarget,
|
|
std::multimap<int, std::tuple<int, double, int>>
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlRemoveParallelEdgesFromEdgesRelations"
|
|
<< endl);
|
|
#endif
|
|
|
|
vector<Tuple*> tupleVectorToDeleteSource;
|
|
vector<Tuple*> tupleVectorToDeleteTarget;
|
|
|
|
for (std::multimap<int, std::tuple<int, double, int>>::iterator
|
|
shortcutsIter =
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted.begin();
|
|
shortcutsIter !=
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted.end();
|
|
++shortcutsIter)
|
|
{
|
|
std::tuple<int, double, int> currTuple =
|
|
(*shortcutsIter).second;
|
|
|
|
int currentSource = (*shortcutsIter).first;
|
|
int currentTarget =
|
|
std::get<HL_INDEX_OF_TARGET_IN_SHORTCUT_TUPLE -
|
|
1>(currTuple);
|
|
|
|
//Prepare Range scan
|
|
//Create From and to by currentSource (=s)
|
|
CcInt currentSourceCcInt(true, currentSource);
|
|
CcInt* currentSourceCcIntPtr =
|
|
¤tSourceCcInt;
|
|
std::vector<void*> vecAttributesFromSource(1);
|
|
vecAttributesFromSource[0] =
|
|
currentSourceCcIntPtr;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesFromSource(1);
|
|
vecAttrTypesFromSource[0] =
|
|
currentSourceCcIntPtr->getSMIKeyType();
|
|
CompositeKey fromSource(vecAttributesFromSource,
|
|
vecAttrTypesFromSource, false);
|
|
|
|
CcInt currentSourceCcIntPlusOne(true,
|
|
currentSourceCcIntPtr->GetIntval() + 1);
|
|
CcInt* currentSourceCcIntPlusOnePtr =
|
|
¤tSourceCcIntPlusOne;
|
|
std::vector<void*> vecAttributesToSource(1);
|
|
vecAttributesToSource[0] =
|
|
currentSourceCcIntPlusOnePtr;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesToSource(1);
|
|
vecAttrTypesToSource[0] =
|
|
currentSourceCcIntPlusOnePtr->getSMIKeyType();
|
|
CompositeKey toSource(vecAttributesToSource,
|
|
vecAttrTypesToSource, false);
|
|
|
|
GenericRelationIterator* currentEdgesOrelSourceIter =
|
|
currentEdgesOrelSource->MakeRangeScan(fromSource, toSource);
|
|
Tuple* currentEdgesOrelSourceTuple =
|
|
currentEdgesOrelSourceIter->GetNextTuple();
|
|
while(currentEdgesOrelSourceTuple)
|
|
{
|
|
CcInt* currentEdgesOrelSourceTupleTargetId =
|
|
(CcInt*) currentEdgesOrelSourceTuple->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
|
|
|
|
//If there is a parallel edge it should be
|
|
// removed from the working-graph
|
|
if(currentEdgesOrelSourceTupleTargetId->GetIntval()
|
|
== currentTarget)
|
|
{
|
|
#ifdef USEDEBUG
|
|
CcInt* currentEdgesOrelSourceTupleSourceId =
|
|
(CcInt*) currentEdgesOrelSourceTuple->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
CcReal* currentEdgesOrelSourceTupleDist =
|
|
(CcReal*) currentEdgesOrelSourceTuple->GetAttribute(
|
|
HL_INDEX_OF_COSTS_IN_EDGE_TUPLE);
|
|
LogDebug("remove incoming edges ST: (" <<
|
|
currentEdgesOrelSourceTupleSourceId->GetIntval()
|
|
<< ", " <<
|
|
currentEdgesOrelSourceTupleTargetId->GetIntval()
|
|
<< ", " <<
|
|
currentEdgesOrelSourceTupleDist->GetRealval() <<
|
|
")"<< endl);
|
|
#endif
|
|
tupleVectorToDeleteSource.push_back(
|
|
currentEdgesOrelSourceTuple);
|
|
|
|
}
|
|
|
|
//dont delete Pointers, we need them later
|
|
currentEdgesOrelSourceTuple = 0;
|
|
currentEdgesOrelSourceTuple =
|
|
currentEdgesOrelSourceIter->GetNextTuple();
|
|
}
|
|
delete currentEdgesOrelSourceIter;
|
|
|
|
//Prepare Range scan
|
|
//Create From and to by currentTarget (=s)
|
|
CcInt currentTargetCcInt(true, currentTarget);
|
|
CcInt* currentTargetCcIntPtr =
|
|
¤tTargetCcInt;
|
|
std::vector<void*> vecAttributesFromTarget(1);
|
|
vecAttributesFromTarget[0] =
|
|
currentTargetCcIntPtr;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesFromTarget(1);
|
|
vecAttrTypesFromTarget[0] =
|
|
currentTargetCcIntPtr->getSMIKeyType();
|
|
CompositeKey fromTarget(vecAttributesFromTarget,
|
|
vecAttrTypesFromTarget, false);
|
|
|
|
CcInt currentTargetCcIntPlusOne(true,
|
|
currentTargetCcIntPtr->GetIntval() + 1);
|
|
CcInt* currentTargetCcIntPlusOnePtr =
|
|
¤tTargetCcIntPlusOne;
|
|
std::vector<void*> vecAttributesToTarget(1);
|
|
vecAttributesToTarget[0] =
|
|
currentTargetCcIntPlusOnePtr;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesToTarget(1);
|
|
vecAttrTypesToTarget[0] =
|
|
currentTargetCcIntPlusOnePtr->getSMIKeyType();
|
|
CompositeKey toTarget(vecAttributesToTarget,
|
|
vecAttrTypesToTarget, false);
|
|
|
|
GenericRelationIterator*
|
|
currentEdgesOrelTargetIter =
|
|
currentEdgesOrelTarget->MakeRangeScan(fromTarget,
|
|
toTarget);
|
|
Tuple* currentEdgesOrelTargetTuple =
|
|
currentEdgesOrelTargetIter->GetNextTuple();
|
|
while(currentEdgesOrelTargetTuple)
|
|
{
|
|
CcInt* currentEdgesOrelTargetTupleSourceId =
|
|
(CcInt*) currentEdgesOrelTargetTuple->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
|
|
//If there is a parallel edge it should be
|
|
// removed from the working-graph
|
|
if(currentEdgesOrelTargetTupleSourceId->GetIntval()
|
|
== currentSource)
|
|
{
|
|
#ifdef USEDEBUG
|
|
CcInt* currentEdgesOrelTargetTupleTargetId =
|
|
(CcInt*) currentEdgesOrelTargetTuple->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
CcReal* currentEdgesOrelTargetTupleDist =
|
|
(CcReal*) currentEdgesOrelTargetTuple->GetAttribute(
|
|
HL_INDEX_OF_COSTS_IN_EDGE_TUPLE);
|
|
LogDebug("remove incoming edges ST: (" <<
|
|
currentEdgesOrelTargetTupleSourceId->GetIntval()
|
|
<< ", " <<
|
|
currentEdgesOrelTargetTupleTargetId->GetIntval()
|
|
<< ", " <<
|
|
currentEdgesOrelTargetTupleDist->GetRealval() <<
|
|
")"<< endl);
|
|
#endif
|
|
tupleVectorToDeleteTarget.push_back(
|
|
currentEdgesOrelTargetTuple);
|
|
|
|
}
|
|
|
|
//dont delete Pointers, we need them later
|
|
currentEdgesOrelTargetTuple = 0;
|
|
currentEdgesOrelTargetTuple =
|
|
currentEdgesOrelTargetIter->GetNextTuple();
|
|
}
|
|
delete currentEdgesOrelTargetIter;
|
|
}
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("iterate tupleVectorToDeleteSource" <<
|
|
endl);
|
|
#endif
|
|
for (vector<Tuple*>::iterator currVectorSourceIter
|
|
= tupleVectorToDeleteSource.begin();
|
|
currVectorSourceIter !=
|
|
tupleVectorToDeleteSource.end();
|
|
++currVectorSourceIter)
|
|
{
|
|
Tuple* tmpTuple2 = *(currVectorSourceIter);
|
|
currentEdgesOrelSource->DeleteTuple(tmpTuple2,
|
|
true); //XXTODO: geht das?
|
|
tmpTuple2->DeleteIfAllowed();
|
|
tmpTuple2 = 0;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("iterate tupleVectorToDeleteTarget" <<
|
|
endl);
|
|
#endif
|
|
for (vector<Tuple*>::iterator currVectorTargetIter
|
|
= tupleVectorToDeleteTarget.begin();
|
|
currVectorTargetIter !=
|
|
tupleVectorToDeleteTarget.end();
|
|
++currVectorTargetIter)
|
|
{
|
|
Tuple* tmpTuple = *(currVectorTargetIter);
|
|
currentEdgesOrelTarget->DeleteTuple(tmpTuple,
|
|
true); //XXTODO: geht das?
|
|
tmpTuple->DeleteIfAllowed();
|
|
tmpTuple = 0;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("end hlRemoveParallelEdgesFromEdgesRelations"
|
|
<< endl);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Scans one of the given Orels (depending on scanBySourceOrTarget) for
|
|
* the given currentNodeSourceOrTarget and only processes if the opposite
|
|
* endpoint is v.
|
|
* If so stores the edge-tuple into the given vector.
|
|
* Scenario:
|
|
* If the outer iteration scanned hlEdgesOrelSource (which gets outgoing
|
|
* edges from v; outer iteration) then scanBySourceOrTarget shall be set
|
|
* to false.
|
|
* In this case currentEdgesOrelSourceOrTarget is equal to
|
|
* hlEdgesOrelTarget.
|
|
* Furthermore this function scans currentEdgesOrelSourceOrTarget by
|
|
* the given targetNode t (inner iteration).
|
|
* For each edge within the inner iteration the function checks whether
|
|
* the sourceNodeId is equal to the given nodeIdV.
|
|
* If so the current tuple is stored into the given vector and the inner
|
|
* iteration will be aborted.
|
|
*
|
|
* @param currentEdgesOrelSourceOrTarget is an OrderedRelation containging
|
|
* all remaining edges of the underlying graph sorted by the field Source
|
|
* @param currentNodeIdV the current contracted node which is used to find
|
|
* only edges incoming to or outgoinf from v
|
|
* @param currentNodeSourceOrTarget the current source or target node which
|
|
* is used to find edges within the opposite orderedRelation
|
|
* @param currentVector the current vector by reference where to store the
|
|
* tuples into found by this function
|
|
* @param scanBySourceOrTarget a boolean to differ whether to scan by
|
|
* source (=true) oder by target (=false)
|
|
* @return true, since the result of this function is the modification
|
|
* of currentEdgesOrelSource and currentEdgesOrelTarget
|
|
*/
|
|
bool hlRemoveContractedEdgesFromEdgesRelationsScanOppositeOrel(
|
|
OrderedRelation* currentEdgesOrelSourceOrTarget,
|
|
int currentNodeIdV,
|
|
CcInt* currentNodeSourceOrTarget,
|
|
vector<Tuple*> ¤tVector,
|
|
bool scanBySourceOrTarget) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlRemoveContractedEdgesFromEdgesRelationsScanOppositeOrel"
|
|
<< endl);
|
|
#endif
|
|
|
|
//Prepare Range scan
|
|
//Create From and to by currentNodeSourceOrTarget
|
|
std::vector<void*> vecAttributesFrom(1);
|
|
vecAttributesFrom[0] = currentNodeSourceOrTarget;
|
|
std::vector<SmiKey::KeyDataType> vecAttrTypesFrom(
|
|
1);
|
|
vecAttrTypesFrom[0] =
|
|
currentNodeSourceOrTarget->getSMIKeyType();
|
|
CompositeKey from(vecAttributesFrom,
|
|
vecAttrTypesFrom, false);
|
|
|
|
CcInt currentNodeSourceOrTargetPlusOne(true,
|
|
currentNodeSourceOrTarget->GetIntval() + 1);
|
|
CcInt* currentNodeSourceOrTargetPlusOnePtr =
|
|
¤tNodeSourceOrTargetPlusOne;
|
|
std::vector<void*> vecAttributesTo(1);
|
|
vecAttributesTo[0] =
|
|
currentNodeSourceOrTargetPlusOnePtr;
|
|
std::vector<SmiKey::KeyDataType> vecAttrTypesTo(
|
|
1);
|
|
vecAttrTypesTo[0] =
|
|
currentNodeSourceOrTargetPlusOnePtr->getSMIKeyType();
|
|
CompositeKey to(vecAttributesTo, vecAttrTypesTo,
|
|
false);
|
|
|
|
GenericRelationIterator*
|
|
currentEdgesOrelSourceOrTargetIter =
|
|
currentEdgesOrelSourceOrTarget->MakeRangeScan(
|
|
from, to);
|
|
Tuple* currentEdgeSourceOrTargetTuple =
|
|
currentEdgesOrelSourceOrTargetIter->GetNextTuple();
|
|
CcInt* currentSourceOrTargetNodeId;
|
|
while(currentEdgeSourceOrTargetTuple)
|
|
{
|
|
//If is scanned by Source, then we need the
|
|
// targetNodeId to compare it with nodeIdV
|
|
if(scanBySourceOrTarget)
|
|
{
|
|
currentSourceOrTargetNodeId = (CcInt*)
|
|
currentEdgeSourceOrTargetTuple->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
}
|
|
else
|
|
{
|
|
currentSourceOrTargetNodeId = (CcInt*)
|
|
currentEdgeSourceOrTargetTuple->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
}
|
|
|
|
if(currentSourceOrTargetNodeId->GetIntval() ==
|
|
currentNodeIdV)
|
|
{
|
|
//only add tuple if edge really is connected to v
|
|
#ifdef USEDEBUG
|
|
LogDebug("pushback: " <<
|
|
currentSourceOrTargetNodeId->GetIntval() << endl);
|
|
#endif
|
|
currentVector.push_back(
|
|
currentEdgeSourceOrTargetTuple);
|
|
}
|
|
else
|
|
{
|
|
currentEdgeSourceOrTargetTuple->DeleteIfAllowed();
|
|
}
|
|
//free resource
|
|
currentEdgeSourceOrTargetTuple = 0;
|
|
currentEdgeSourceOrTargetTuple =
|
|
currentEdgesOrelSourceOrTargetIter->GetNextTuple();
|
|
}
|
|
delete currentEdgesOrelSourceOrTargetIter;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("end hlRemoveContractedEdgesFromEdgesRelationsScanOppositeOrel"
|
|
<< endl);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
static const string hlForwardLabelColumnName()
|
|
{
|
|
return "ForwardLabel";
|
|
}
|
|
static const string hlReverseLabelColumnName()
|
|
{
|
|
return "ReverseLabel";
|
|
}
|
|
|
|
/*
|
|
* NestedRelation type for the set containing all labels.
|
|
* Used for creation of new NestedRelations,
|
|
* new Tuples of this NestedRelations
|
|
* or cloning or deleting of an NestedRelations of this type
|
|
*/
|
|
static const string hlGetAllLabelsTypeInfo()
|
|
{
|
|
return "(" + NestedRelation::BasicType() +
|
|
"(" + Tuple::BasicType() +
|
|
"(" +
|
|
"(SourceNodeId " + CcInt::BasicType() + ")" +
|
|
"(" + hlForwardLabelColumnName() + " " +
|
|
hlGetForwardOrReverseLabelArelTypeInfo() + ")" +
|
|
"(" + hlReverseLabelColumnName() + " " +
|
|
hlGetForwardOrReverseLabelArelTypeInfo() + ")" +
|
|
")" +
|
|
")" +
|
|
")";
|
|
}
|
|
|
|
/*
|
|
* Relation type for forward and reverse labels.
|
|
* Used for creation of new Relation Objects representing
|
|
* a forward or reverse label.
|
|
* Used for Testing-Operator
|
|
*/
|
|
static const string
|
|
hlGetForwardOrReverseLabelTypeInfo()
|
|
{
|
|
return "(" + Relation::BasicType() +
|
|
hlGetForwardOrReverseLabelTupleTypeInfo() +
|
|
")";
|
|
}
|
|
|
|
/*
|
|
* AttributeRelation type for forward and reverse labels.
|
|
* Used for creation of new AttributeRelation Objects, new
|
|
* Tuples of this AttributeRelation
|
|
* or cloning or deleting of an AttributeRelation of this type
|
|
*/
|
|
static const string
|
|
hlGetForwardOrReverseLabelArelTypeInfo() //XXTODO: geht das?
|
|
{
|
|
return "(" + AttributeRelation::BasicType() +
|
|
hlGetForwardOrReverseLabelTupleTypeInfo() +
|
|
")";
|
|
}
|
|
|
|
/*
|
|
* Tuple type for forward and reverse labels.
|
|
* Used for creation of new Relation Objects, new Tuples of this Relation
|
|
* or cloning or deleting of an Relation of this type
|
|
*/
|
|
static const string
|
|
hlGetForwardOrReverseLabelTupleTypeInfo()
|
|
{
|
|
return "(" + Tuple::BasicType() +
|
|
"(" +
|
|
"(HubNodeIdNew " + CcInt::BasicType() + ")" +
|
|
"(HubNodeId " + CcInt::BasicType() + ")" +
|
|
"(HubParentNodeId " + CcInt::BasicType() + ")" +
|
|
"(HubParentNodeTupleId " + CcInt::BasicType() +
|
|
")" +
|
|
"(HubDistanceToSource " + CcReal::BasicType() +
|
|
")" +
|
|
")" +
|
|
")";
|
|
}
|
|
|
|
/*
|
|
* Definition of Field-Indexes for NestedRelation allLabels
|
|
*/
|
|
static const int
|
|
HL_INDEX_OF_NODE_ID_IN_ALL_LABELS_TUPLE = 0;
|
|
static const int
|
|
HL_INDEX_OF_FORWARD_LABEL_IN_ALL_LABELS_TUPLE = 1;
|
|
static const int
|
|
HL_INDEX_OF_REVERSE_LABEL_IN_ALL_LABELS_TUPLE = 2;
|
|
|
|
/*
|
|
* Definition of Field-Indexes for AttributeRelation forwardOrReverseLabel
|
|
*/
|
|
static const int
|
|
HL_INDEX_OF_HUB_NODE_ID_NEW_IN_LABEL_TUPLE = 0;
|
|
static const int
|
|
HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE = 1;
|
|
static const int
|
|
HL_INDEX_OF_HUB_PARENT_NODE_ID_IN_LABEL_TUPLE = 2;
|
|
static const int
|
|
HL_INDEX_OF_HUB_PARENT_TUPLE_ID_IN_LABEL_TUPLE =
|
|
3;
|
|
static const int
|
|
HL_INDEX_OF_HUB_DISTANCE_TO_SOURCE_IN_LABEL_TUPLE
|
|
= 4;
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Creates a Lable (either forward or reverse) for every node
|
|
* in nodesRankedDescOrelRank.
|
|
*
|
|
* @param allLabelsNrel is an NestedRelation representing the result
|
|
* of this operator
|
|
* @param nodesRankedDescOrelRank is an OrderedRelation containging all
|
|
* nodes of the underlying graph sorted by the field NodeIdNew
|
|
* @param edgesContractedUpwardsOrelSource is an OrderedRelation
|
|
* containging all edges of the underlying graph sorted by the field Source
|
|
* @param edgesContractedDownwardsOrelTarget is an OrderedRelation
|
|
* containging all edges of the underlying graph sorted by the field Target
|
|
* @param hHop is a an integer which defines the h-Hop-Size used for
|
|
* local look-up queries which is used for stalling on demand
|
|
* @return true since the result is stored in the gviven allLabelsNrel
|
|
*/
|
|
bool hlCreateLabels(NestedRelation* allLabelsNrel,
|
|
BTree* bTreeNodesRankedDescOrelRank,
|
|
OrderedRelation* nodesRankedDescOrelRank,
|
|
OrderedRelation* edgesContractedUpwardsOrelSource,
|
|
OrderedRelation*
|
|
edgesContractedDownwardsOrelTarget,
|
|
int hHop) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlCreateLabels" << endl);
|
|
#endif
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("create forward and reverse relation containing label-data"
|
|
" used by all single forward and reverse labels"
|
|
<< endl);
|
|
#endif
|
|
SubRelation* forwardDataSubRel =
|
|
allLabelsNrel->getSubRel(
|
|
hlForwardLabelColumnName());
|
|
SubRelation* reverseDataSubRel =
|
|
allLabelsNrel->getSubRel(
|
|
hlReverseLabelColumnName());
|
|
|
|
SmiFileId forwardDataSubRelFileId =
|
|
forwardDataSubRel->fileId;
|
|
SmiFileId reverseDataSubRelFileId =
|
|
reverseDataSubRel->fileId;
|
|
|
|
ListExpr forwardDataSubRelTypeInfo =
|
|
forwardDataSubRel->typeInfo;
|
|
ListExpr reverseDataSubRelTypeInfo =
|
|
reverseDataSubRel->typeInfo;
|
|
|
|
Relation* forwardDataRel = forwardDataSubRel->rel;
|
|
Relation* reverseDataRel = reverseDataSubRel->rel;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("do while" << endl);
|
|
#endif
|
|
GenericRelationIterator* nodesRankIter =
|
|
nodesRankedDescOrelRank->MakeScan();
|
|
//XXTODO: iteration in der iteration???
|
|
Tuple* currentNodeV =
|
|
nodesRankIter->GetNextTuple();
|
|
|
|
while(currentNodeV)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("next iteration" << endl);
|
|
#endif
|
|
|
|
CcInt* nodeIdV = (CcInt*)
|
|
currentNodeV->GetAttribute(
|
|
HL_INDEX_OF_ID_IN_NODES_RANKED);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("prepare NestedRelationTuple" << endl);
|
|
#endif
|
|
|
|
TupleType* tupleTypeAllLabels =
|
|
allLabelsNrel->getPrimary()->GetTupleType();
|
|
Tuple* allLabelsTuple = new Tuple(
|
|
tupleTypeAllLabels);
|
|
allLabelsTuple->PutAttribute(
|
|
HL_INDEX_OF_NODE_ID_IN_ALL_LABELS_TUPLE,
|
|
new CcInt(true, nodeIdV->GetIntval()));
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("forward and reverse label multimaps" <<
|
|
endl);
|
|
#endif
|
|
std::multimap<int, std::tuple<int, int, double>>
|
|
labelForwardMultimap;
|
|
std::multimap<int, std::tuple<int, int, double>>
|
|
labelReverseMultimap;
|
|
|
|
bool isForward = true;
|
|
//Create forward label
|
|
#ifdef USEDEBUG
|
|
LogDebug("create forward label" << endl);
|
|
#endif
|
|
hlCreateLabelByDijkstraWithStalling(
|
|
bTreeNodesRankedDescOrelRank,
|
|
nodesRankedDescOrelRank,
|
|
edgesContractedUpwardsOrelSource,
|
|
edgesContractedDownwardsOrelTarget,
|
|
labelForwardMultimap, nodeIdV, hHop, isForward);
|
|
#ifdef USEDEBUG
|
|
LogDebug("fully prune forward label" << endl);
|
|
#endif
|
|
//hlPruneLabelByBootstrapping(allLabelsNrel,
|
|
// labelForwardMultimap, nodeIdV, isForward);
|
|
#ifdef USEDEBUG
|
|
LogDebug("create and fill forwardLabel" << endl);
|
|
#endif
|
|
AttributeRelation* labelForwardArel = new
|
|
AttributeRelation(forwardDataSubRelFileId,
|
|
forwardDataSubRelTypeInfo,
|
|
labelForwardMultimap.size());
|
|
labelForwardArel->setPartOfNrel(true);
|
|
hlFillForwardOrReverseLabel(labelForwardArel,
|
|
forwardDataRel, labelForwardMultimap);
|
|
#ifdef USEDEBUG
|
|
LogDebug("add forward label to all labels" << endl);
|
|
#endif
|
|
allLabelsTuple->PutAttribute(
|
|
HL_INDEX_OF_FORWARD_LABEL_IN_ALL_LABELS_TUPLE,
|
|
labelForwardArel);
|
|
|
|
//Create reverse label
|
|
isForward = false;
|
|
#ifdef USEDEBUG
|
|
LogDebug("create reverse label" << endl);
|
|
#endif
|
|
hlCreateLabelByDijkstraWithStalling(
|
|
bTreeNodesRankedDescOrelRank,
|
|
nodesRankedDescOrelRank,
|
|
edgesContractedUpwardsOrelSource,
|
|
edgesContractedDownwardsOrelTarget,
|
|
labelReverseMultimap, nodeIdV, hHop, isForward);
|
|
#ifdef USEDEBUG
|
|
LogDebug("fully prune reverse label" << endl);
|
|
#endif
|
|
//hlPruneLabelByBootstrapping(allLabelsNrel,
|
|
// labelReverseMultimap, nodeIdV, isForward);
|
|
#ifdef USEDEBUG
|
|
LogDebug("create and fill reverseLabel" << endl);
|
|
#endif
|
|
AttributeRelation* labelReverseArel = new
|
|
AttributeRelation(reverseDataSubRelFileId,
|
|
reverseDataSubRelTypeInfo,
|
|
labelReverseMultimap.size());
|
|
labelReverseArel->setPartOfNrel(true);
|
|
hlFillForwardOrReverseLabel(labelReverseArel,
|
|
reverseDataRel, labelReverseMultimap);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("add reverse label to all labels" << endl);
|
|
#endif
|
|
allLabelsTuple->PutAttribute(
|
|
HL_INDEX_OF_REVERSE_LABEL_IN_ALL_LABELS_TUPLE,
|
|
labelReverseArel);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish current all labels Tuple" << endl);
|
|
#endif
|
|
allLabelsNrel->getPrimary()->AppendTuple(
|
|
allLabelsTuple);
|
|
|
|
allLabelsTuple->DeleteIfAllowed();
|
|
|
|
allLabelsTuple = 0;
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get next tuple" << endl);
|
|
#endif
|
|
//Free Outgoing-Iteration
|
|
currentNodeV->DeleteIfAllowed();
|
|
currentNodeV = 0;
|
|
currentNodeV = nodesRankIter->GetNextTuple();
|
|
}
|
|
|
|
delete nodesRankIter;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("reorder labels" << endl);
|
|
#endif
|
|
//hlReorderLabels(); //XXTODO
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlCreateLabels" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Adds all Hubs of the given Label to the corresponding Attribute-
|
|
* and Data-Relation
|
|
*
|
|
* @param fwdOrRvsLabelArel is an AttributeRelation to be filled with
|
|
* data from the given multimap
|
|
* @param fwdOrRvsDataRel is an Relation to be filled with data from the
|
|
* given multimap
|
|
* @param fwdOrRvsLabelMultimap is a Multimap containging all final
|
|
* Label-Data
|
|
* @return true, since all modification will be done within the
|
|
* given parameters
|
|
*/
|
|
bool hlFillForwardOrReverseLabel(
|
|
AttributeRelation* fwdOrRvsLabelArel,
|
|
Relation* fwdOrRvsDataRel,
|
|
std::multimap<int, std::tuple<int, int, double>>
|
|
&fwdOrRvsLabelMultimap) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlFillForwardOrReverseLabel" <<
|
|
endl);
|
|
#endif
|
|
|
|
std::multimap<int, int> tmpIndexTupleIds;
|
|
for (std::multimap<int, std::tuple<int, int, double>>::iterator
|
|
fwdOrRvsLabelMultimapIter =
|
|
fwdOrRvsLabelMultimap.begin();
|
|
fwdOrRvsLabelMultimapIter !=
|
|
fwdOrRvsLabelMultimap.end();
|
|
++fwdOrRvsLabelMultimapIter)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("next iteration" << endl);
|
|
#endif
|
|
|
|
int currNodeIdNew =
|
|
(*fwdOrRvsLabelMultimapIter).first;
|
|
std::tuple<int, int, double> currTuple =
|
|
(*fwdOrRvsLabelMultimapIter).second;
|
|
int currNodeId =
|
|
std::get<HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE -
|
|
1>(currTuple);
|
|
int currParentNodeId =
|
|
std::get<HL_INDEX_OF_HUB_PARENT_NODE_ID_IN_LABEL_TUPLE
|
|
- 1>(currTuple);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("currNode rank: " << currNodeIdNew <<
|
|
" id: " << currNodeId << " parent: " <<
|
|
currParentNodeId << endl);
|
|
#endif
|
|
|
|
TupleType* tt1 = fwdOrRvsDataRel->GetTupleType();
|
|
Tuple* relInsertTuple = new Tuple(tt1);
|
|
|
|
|
|
//get tupleId of currParentNodeId from temporal structure
|
|
#ifdef USEDEBUG
|
|
LogDebug("suche nach parent von " << currParentNodeId
|
|
<< " anzahl gesamt vorhanden: " <<
|
|
tmpIndexTupleIds.size() << endl);
|
|
#endif
|
|
std::multimap<int, int>::iterator
|
|
parentTupleIdIter = tmpIndexTupleIds.find(
|
|
currParentNodeId);
|
|
|
|
//only check distances when current min tuple from h-hop
|
|
// reverse search does exist in current forward label
|
|
int currParentTupleId = -1;
|
|
if(parentTupleIdIter != tmpIndexTupleIds.end())
|
|
{
|
|
currParentTupleId = (*parentTupleIdIter).second;
|
|
#ifdef USEDEBUG
|
|
LogDebug("parent tupleId found (" <<
|
|
currParentTupleId << ") of parent nodeId: " <<
|
|
currParentNodeId << " for currTuple: " <<
|
|
currNodeId << endl);
|
|
#endif
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("Add data to Data-Relation" << endl);
|
|
#endif
|
|
relInsertTuple->PutAttribute(
|
|
HL_INDEX_OF_HUB_NODE_ID_NEW_IN_LABEL_TUPLE,
|
|
new CcInt(true, currNodeIdNew));
|
|
relInsertTuple->PutAttribute(
|
|
HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE,
|
|
new CcInt(true, currNodeId));
|
|
relInsertTuple->PutAttribute(
|
|
HL_INDEX_OF_HUB_PARENT_NODE_ID_IN_LABEL_TUPLE,
|
|
new CcInt(true, currParentNodeId));
|
|
relInsertTuple->PutAttribute(
|
|
HL_INDEX_OF_HUB_PARENT_TUPLE_ID_IN_LABEL_TUPLE,
|
|
new CcInt(true, currParentTupleId));
|
|
relInsertTuple->PutAttribute(
|
|
HL_INDEX_OF_HUB_DISTANCE_TO_SOURCE_IN_LABEL_TUPLE,
|
|
new CcReal(true,
|
|
std::get<HL_INDEX_OF_HUB_DISTANCE_TO_SOURCE_IN_LABEL_TUPLE
|
|
- 2>(currTuple)));
|
|
fwdOrRvsDataRel->AppendTuple(relInsertTuple);
|
|
|
|
TupleId relInsertTupleId =
|
|
relInsertTuple->GetTupleId();
|
|
|
|
fwdOrRvsLabelArel->Append(relInsertTupleId);
|
|
|
|
//save nodeId and tupleId in temporal structure
|
|
tmpIndexTupleIds.insert(pair<int, int>(currNodeId,
|
|
relInsertTupleId));
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("Free Resources" << endl);
|
|
#endif
|
|
relInsertTuple->DeleteIfAllowed();
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlFillForwardOrReverseLabel" <<
|
|
endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Scans the nodes Relation for the given nodeId and extracts
|
|
* the rank of the node and returns it.
|
|
* Returns -1 if no adequate
|
|
*
|
|
* @param nodesRanked is an OrderedRelation containging all
|
|
* nodes of the graph with their rank
|
|
* @param givenNodeId is the given nodeId
|
|
* @return the rank extracted or -1 if no node was found
|
|
*/
|
|
int hlGetRankById(BTree* btreeNodesRanked,
|
|
OrderedRelation* nodesRanked,
|
|
CcInt* givenNodeId) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlGetRankById" << endl);
|
|
#endif
|
|
|
|
int resultingRank = -1;
|
|
int tupleIdRankedNodeInt = -1;
|
|
|
|
BTreeIterator* btreeNodesRankedIter =
|
|
btreeNodesRanked->ExactMatch(givenNodeId);
|
|
|
|
if(btreeNodesRankedIter)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("using btree iterator" << endl);
|
|
#endif
|
|
if(btreeNodesRankedIter->Next())
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("next iterated element" << endl);
|
|
#endif
|
|
tupleIdRankedNodeInt =
|
|
btreeNodesRankedIter->GetId();
|
|
#ifdef USEDEBUG
|
|
LogDebug("tupleId: " << tupleIdRankedNodeInt <<
|
|
endl);
|
|
#endif
|
|
}
|
|
delete btreeNodesRankedIter;
|
|
}
|
|
|
|
TupleId tupleIdRankedNode = (TupleId)
|
|
tupleIdRankedNodeInt;
|
|
|
|
Tuple* rankedNodeTuple = nodesRanked->GetTuple(
|
|
tupleIdRankedNode, false);
|
|
|
|
if(!rankedNodeTuple) //XXTODO Debug/ korrigieren,
|
|
// obiges findet kein tuple
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Warning, no tuple found" << endl);
|
|
#endif
|
|
GenericRelationIterator* nodesRankedIter =
|
|
nodesRanked->MakeScan();
|
|
Tuple* tmpTuple = nodesRankedIter->GetNextTuple();
|
|
while(tmpTuple)
|
|
{
|
|
|
|
CcInt* tmpId = (CcInt*) tmpTuple->GetAttribute(
|
|
HL_INDEX_OF_ID_IN_NODES_RANKED);
|
|
#ifdef USEDEBUG
|
|
LogDebug("next iteration nodeId: " <<
|
|
tmpId->GetIntval() << endl);
|
|
#endif
|
|
|
|
if(tmpId->GetIntval() == givenNodeId->GetIntval())
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("right tuple found, going to break" <<
|
|
endl);
|
|
#endif
|
|
rankedNodeTuple = tmpTuple;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
tmpTuple->DeleteIfAllowed();
|
|
tmpTuple = 0;
|
|
tmpTuple = nodesRankedIter->GetNextTuple();
|
|
}
|
|
}
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish iteration" << endl);
|
|
#endif
|
|
delete nodesRankedIter;
|
|
}
|
|
|
|
if(rankedNodeTuple)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("tuple found" << endl);
|
|
#endif
|
|
CcInt* currentRank = (CcInt*)
|
|
rankedNodeTuple->GetAttribute(
|
|
HL_INDEX_OF_RANK_IN_NODES_RANKED);
|
|
resultingRank = currentRank->GetIntval();
|
|
rankedNodeTuple->DeleteIfAllowed();
|
|
#ifdef USEDEBUG
|
|
LogDebug("node: " << givenNodeId->GetIntval() <<
|
|
" rank: "<< currentRank->GetIntval() << endl);
|
|
#endif
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("end hlGetRankById" << endl);
|
|
#endif
|
|
|
|
return resultingRank;
|
|
}
|
|
|
|
|
|
/*
|
|
* Creates a Lable (either forward or reverse) for the given source node.
|
|
*
|
|
* @param edgesContractedUpwardsOrelSource is an OrderedRelation
|
|
* containging all edges of the underlying graph sorted by the field Source
|
|
* @param edgesContractedDownwardsOrelTarget is an OrderedRelation
|
|
* containging all edges of the underlying graph sorted by the field Target
|
|
* @param fwdOrRvsLabelMultimap must be an empty Multimap representing the
|
|
* label which will be filled by this method
|
|
* @param givenSourceIdS is the vertext ID of the current source node s for
|
|
* which the labels shall be created
|
|
* @param hHop is a an integer which defines the h-Hop-Size used for local
|
|
* look-up queries which is used for stalling on demand
|
|
* @param isForward is a boolean that indicates whether a forward or
|
|
* reverselabel shall be created
|
|
* @return true since the result of this method is storen into
|
|
* fwdOrRvsLabelMultimap
|
|
*/
|
|
bool hlCreateLabelByDijkstraWithStalling(
|
|
BTree* btreeNodesRanked,
|
|
OrderedRelation* nodesRanked,
|
|
OrderedRelation* edgesContractedUpwardsOrelSource,
|
|
OrderedRelation*
|
|
edgesContractedDownwardsOrelTarget,
|
|
std::multimap<int, std::tuple<int, int, double>>
|
|
&fwdOrRvsLabelMultimap, CcInt* givenSourceIdS,
|
|
int hHop, bool isForward) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlCreateLabelByDijkstraWithStalling"
|
|
<< endl);
|
|
#endif
|
|
int currRank = -1;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("insert source node itself into label" <<
|
|
endl);
|
|
#endif
|
|
currRank = hlGetRankById(btreeNodesRanked,
|
|
nodesRanked, givenSourceIdS);
|
|
std::tuple<int, int, double> insertTupleSource =
|
|
std::make_tuple(givenSourceIdS->GetIntval(), -1,
|
|
0.0);
|
|
fwdOrRvsLabelMultimap.insert(
|
|
pair<int, std::tuple<int, int, double>>(currRank,
|
|
insertTupleSource));
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("create labelNotYetVisitedNodes" << endl);
|
|
#endif
|
|
std::multimap<double, std::tuple<int, int>>
|
|
labelNotYetVisitedNodes;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("create stillVisitedNodes" << endl);
|
|
#endif
|
|
std::vector<int> labelStillVisitedNodes;
|
|
labelStillVisitedNodes.push_back(
|
|
givenSourceIdS->GetIntval());
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("process initial edges" << endl);
|
|
#endif
|
|
hlCreateLabelScanNewVertices(
|
|
labelNotYetVisitedNodes, labelStillVisitedNodes,
|
|
edgesContractedUpwardsOrelSource,
|
|
edgesContractedDownwardsOrelTarget,
|
|
givenSourceIdS, 0.0, isForward);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("process iterative edges" << endl);
|
|
#endif
|
|
while(labelNotYetVisitedNodes.size() > 0)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("get next minV" << endl);
|
|
#endif
|
|
std::multimap<double, std::tuple<int, int>>::iterator
|
|
labelNotYetVisitedNodesIter =
|
|
labelNotYetVisitedNodes.begin();
|
|
double currMinVDist =
|
|
(*labelNotYetVisitedNodesIter).first;
|
|
|
|
std::tuple<int, int> currMinVPartTuple =
|
|
(*labelNotYetVisitedNodesIter).second;
|
|
int currMinVNodeId =
|
|
std::get<HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED -
|
|
1>(currMinVPartTuple);
|
|
int currMinVParentNodeId =
|
|
std::get<HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED
|
|
- 1>(currMinVPartTuple);
|
|
CcInt* currMinVNodeIdCcInt = new CcInt(true,
|
|
currMinVNodeId);
|
|
//zwingend per new erzeugen?
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("remove tuple from orel" << endl);
|
|
#endif
|
|
labelNotYetVisitedNodes.erase(
|
|
labelNotYetVisitedNodesIter);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("Add to still visited Nodes" << endl);
|
|
#endif
|
|
labelStillVisitedNodes.push_back(currMinVNodeId);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("check for witness before inserting by doing"
|
|
" h-Hop-Reverse-Search"
|
|
<< endl);
|
|
#endif
|
|
bool isPruned = hlCreateLabelCheckForWitness(
|
|
fwdOrRvsLabelMultimap,
|
|
edgesContractedUpwardsOrelSource,
|
|
edgesContractedDownwardsOrelTarget,
|
|
currMinVNodeIdCcInt, currMinVDist, hHop,
|
|
isForward);
|
|
|
|
if(!isPruned)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("append tuple to label" << endl);
|
|
#endif
|
|
currRank = -1;
|
|
currRank = hlGetRankById(btreeNodesRanked,
|
|
nodesRanked, currMinVNodeIdCcInt);
|
|
std::tuple<int, int, double> insertTupleLabel =
|
|
std::make_tuple(currMinVNodeId,
|
|
currMinVParentNodeId, currMinVDist);
|
|
fwdOrRvsLabelMultimap.insert(
|
|
pair<int, std::tuple<int, int, double>>(currRank,
|
|
insertTupleLabel));
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("scan new vertices" << endl);
|
|
#endif
|
|
hlCreateLabelScanNewVertices(
|
|
labelNotYetVisitedNodes, labelStillVisitedNodes,
|
|
edgesContractedUpwardsOrelSource,
|
|
edgesContractedDownwardsOrelTarget,
|
|
currMinVNodeIdCcInt, currMinVDist, isForward);
|
|
}
|
|
|
|
currMinVNodeIdCcInt->DeleteIfAllowed(
|
|
true); //TODO: notwendig? bei getAttribute auch nicht notwendig
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlCreateLabelByDijkstraWithStalling"
|
|
<< endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Scans for new vertices during dijkstra forward or reverse search used
|
|
* to create labels
|
|
*
|
|
* @param labelNotYetVisitedNodes is a Multimap by reference storing the
|
|
* vertices which are not yet visited by the dijkstra search
|
|
* @param labelStillVisitedNodes is a vector by reference storing the
|
|
* vertices which are still visited by the dijkstra search
|
|
* @param edgesContractedUpwardsOrelSource is an OrderedRelation
|
|
* containging all edges of the underlying graph sorted by the field Source
|
|
* @param edgesContractedDownwardsOrelTarget is an OrderedRelation
|
|
* containging all edges of the underlying graph sorted by the field Target
|
|
* @param givenSourceIdV is the vertext ID of the current source node v
|
|
* which was chosen as next vertex during dijkstra search
|
|
* @param givenDistSV contains the weighted distance from the original
|
|
* source s to the current given node v
|
|
* @param isForward is a boolean that indicates whether a forward or
|
|
* reverselabel shall be created
|
|
* @return true since the result of this method is stored into
|
|
* labelNotYetVisitedNodes
|
|
*/
|
|
bool hlCreateLabelScanNewVertices(
|
|
std::multimap<double, std::tuple<int, int>>
|
|
&labelNotYetVisitedNodes,
|
|
std::vector<int> &labelStillVisitedNodes,
|
|
OrderedRelation* edgesContractedUpwardsOrelSource,
|
|
OrderedRelation*
|
|
edgesContractedDownwardsOrelTarget,
|
|
CcInt* givenSourceIdV, double givenDistSV,
|
|
bool isForward) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Start hlCreateLabelScanNewVertices with isForward = "
|
|
<< isForward << endl);
|
|
#endif
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("prepare iteration" << endl);
|
|
#endif
|
|
//iterate over all outgoing edges (v, w) (on forward search,
|
|
// vice versa else)
|
|
//Prepare Range scan
|
|
//Create From and to by givenSourceIdV (=V)
|
|
std::vector<void*> vecAttributesFromSourceV(1);
|
|
vecAttributesFromSourceV[0] = givenSourceIdV;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesFromSourceV(1);
|
|
vecAttrTypesFromSourceV[0] =
|
|
givenSourceIdV->getSMIKeyType();
|
|
CompositeKey fromSourceV(vecAttributesFromSourceV,
|
|
vecAttrTypesFromSourceV, false);
|
|
|
|
CcInt currentNodePlusOneSourceV(true,
|
|
givenSourceIdV->GetIntval() + 1);
|
|
CcInt* currentNodePlusOnePtrSourceV =
|
|
¤tNodePlusOneSourceV;
|
|
std::vector<void*> vecAttributesToSourceV(1);
|
|
vecAttributesToSourceV[0] =
|
|
currentNodePlusOnePtrSourceV;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesToSourceV(1);
|
|
vecAttrTypesToSourceV[0] =
|
|
currentNodePlusOnePtrSourceV->getSMIKeyType();
|
|
CompositeKey toSourceV(vecAttributesToSourceV,
|
|
vecAttrTypesToSourceV, false);
|
|
|
|
GenericRelationIterator*
|
|
edgesContractedUpOrDownOrelSourceOrTargetIter;
|
|
Tuple* currentContractedEdgeVW;
|
|
if(isForward)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("get outgoing edges (v, w) within upwardsgraph"
|
|
<< endl);
|
|
#endif
|
|
edgesContractedUpOrDownOrelSourceOrTargetIter =
|
|
edgesContractedUpwardsOrelSource->MakeRangeScan(
|
|
fromSourceV, toSourceV);
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("get incoming edges (w, v) within downwardsgraph"
|
|
<< endl);
|
|
#endif
|
|
edgesContractedUpOrDownOrelSourceOrTargetIter =
|
|
edgesContractedDownwardsOrelTarget->MakeRangeScan(
|
|
fromSourceV, toSourceV);
|
|
}
|
|
currentContractedEdgeVW =
|
|
edgesContractedUpOrDownOrelSourceOrTargetIter->GetNextTuple();
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("iterate and store outgoing/ incoming egdes (v, w)/ (w, v)"
|
|
" into labelNotYetVisited"
|
|
<< endl);
|
|
#endif
|
|
while(currentContractedEdgeVW)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("next iteration" << endl);
|
|
#endif
|
|
CcInt* currentSourceOrTargetW;
|
|
if(isForward)
|
|
{
|
|
currentSourceOrTargetW = (CcInt*)
|
|
currentContractedEdgeVW->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
}
|
|
else
|
|
{
|
|
currentSourceOrTargetW = (CcInt*)
|
|
currentContractedEdgeVW->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
}
|
|
|
|
if(std::find(labelStillVisitedNodes.begin(),
|
|
labelStillVisitedNodes.end(),
|
|
currentSourceOrTargetW->GetIntval()) ==
|
|
labelStillVisitedNodes.end())
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("append tuple to labelNotYet" << endl);
|
|
#endif
|
|
|
|
//create auxiliary data
|
|
//hopDepth is set to -1 because it doesnt matter but its
|
|
// increased during insertOrUpdate and stored within
|
|
// labelNotYet which does not have any effect yet but
|
|
// is kind of 'dirty'
|
|
std::tuple<double, int, int>
|
|
currParentNotYetMultimapTuple = std::make_tuple(
|
|
givenDistSV, givenSourceIdV->GetIntval(), -1);
|
|
|
|
//isHHop = false means to use the parentsNodeId
|
|
// instead of the parentsHopDepth to store within notYet
|
|
bool isHHop = false;
|
|
#ifdef USEDEBUG
|
|
LogDebug("insert or update" << endl);
|
|
#endif
|
|
//Either insert the new scanned W/V into not visited
|
|
// list or update it if it sill exists and has a shorter
|
|
// path via current v
|
|
hlInsertOrUpdateTupleInNotYetVisitedList(-1,
|
|
currParentNotYetMultimapTuple,
|
|
currentContractedEdgeVW, labelNotYetVisitedNodes,
|
|
isForward, isHHop);
|
|
#ifdef USEDEBUG
|
|
LogDebug("inserted or updated" << endl);
|
|
#endif
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get next tuple" << endl);
|
|
#endif
|
|
//Free Outgoing-Iteration
|
|
currentContractedEdgeVW->DeleteIfAllowed();
|
|
currentContractedEdgeVW = 0;
|
|
currentContractedEdgeVW =
|
|
edgesContractedUpOrDownOrelSourceOrTargetIter->GetNextTuple();
|
|
}
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish iteration" << endl);
|
|
#endif
|
|
|
|
//Free resources
|
|
delete edgesContractedUpOrDownOrelSourceOrTargetIter;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("end hlCreateLabelScanNewVertices" << endl);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Scans for new vertices during dijkstra h-Hop reverse or forward
|
|
* search used to check the previously found node
|
|
* for a witness path in the opposite graph. see also
|
|
* hlCreateLabelCheckForWitness;
|
|
*
|
|
* @param fwdOrRvsLabelMultimap is a Multimap representing the label
|
|
* which will be filled by this method
|
|
* @param reverseNotYetVisitedNodes is an OrderedRelation storing the
|
|
* vertices which are not yet visited by the h-hop reverse search
|
|
* @param edgesContractedUpwardsOrelSource is an OrderedRelation
|
|
* containging all edges of the underlying upwardsgraph sorted by
|
|
* the field Source
|
|
* @param edgesContractedDownwardsOrelTarget is an OrderedRelation
|
|
* containging all edges of the underlying downwardsgraph sorted by
|
|
* the field Target
|
|
* @param fwdCurrSourceOrTargetW is the vertext ID of the current node
|
|
* w which was chosen as next vertex during forward (or reverse) search
|
|
* for which a witness path shall be found
|
|
* @param fwdDistSW is a double representing the weighted distance
|
|
* between the actual source node s of this label and the given node
|
|
* w during forward (or reverse) search
|
|
* @param hHop is a an integer representing maximum allowed hop-size
|
|
* used during this h-hop-reverse-search
|
|
* @param isForward is a boolean that indicates whether a forward or
|
|
* reverselabel shall be created
|
|
* @return true if the given node needs to be pruned out, false else
|
|
*/
|
|
bool hlCreateLabelCheckForWitness(
|
|
std::multimap<int, std::tuple<int, int, double>>
|
|
&fwdOrRvsLabelMultimap,
|
|
OrderedRelation* edgesContractedUpwardsOrelSource,
|
|
OrderedRelation*
|
|
edgesContractedDownwardsOrelTarget,
|
|
CcInt* fwdCurrSourceOrTargetW, double fwdDistSW,
|
|
int hHop, bool isForward) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Start hlCreateLabelCheckForWitness" <<
|
|
endl);
|
|
#endif
|
|
bool isPruned = false;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("create reverseNotYetVisitedNodes" << endl);
|
|
#endif
|
|
std::multimap<double, std::tuple<int, int>>
|
|
reverseNotYetVisitedNodes;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("create stillVisitedNodes" << endl);
|
|
#endif
|
|
std::vector<int> stillVisitedNodes;
|
|
stillVisitedNodes.push_back(
|
|
fwdCurrSourceOrTargetW->GetIntval());
|
|
|
|
//scan new vertices in h-hop reverse search
|
|
hlCreateLabelCheckForWitnessScanNewVertices(
|
|
reverseNotYetVisitedNodes, stillVisitedNodes,
|
|
edgesContractedUpwardsOrelSource,
|
|
edgesContractedDownwardsOrelTarget,
|
|
fwdCurrSourceOrTargetW, 0.0, 0, isForward);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("process iterative edges in hHop-reverse" <<
|
|
endl);
|
|
#endif
|
|
while(reverseNotYetVisitedNodes.size() > 0)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("next iteration witness" << endl);
|
|
#endif
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get next revMinV" << endl);
|
|
#endif
|
|
std::multimap<double, std::tuple<int, int>>::iterator
|
|
reverseNotYetVisitedNodesIter =
|
|
reverseNotYetVisitedNodes.begin();
|
|
double revMinVDistToW =
|
|
(*reverseNotYetVisitedNodesIter).first;
|
|
|
|
std::tuple<int, int> currRevMinVTuple =
|
|
(*reverseNotYetVisitedNodesIter).second;
|
|
int revMinVNodeID =
|
|
std::get<HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED -
|
|
1>(currRevMinVTuple);
|
|
int revMinVHopDepth =
|
|
std::get<HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED
|
|
- 1>(currRevMinVTuple);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("remove tuple from orel" << endl);
|
|
#endif
|
|
reverseNotYetVisitedNodes.erase(
|
|
reverseNotYetVisitedNodesIter);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("check for witness for: " << revMinVNodeID
|
|
<< endl);
|
|
#endif
|
|
std::multimap<int, std::tuple<int, int, double>>::iterator
|
|
fwdOrRvsLabelMultimapIter =
|
|
fwdOrRvsLabelMultimap.find(revMinVNodeID);
|
|
|
|
//only check distances when current min tuple from h-hop
|
|
// reverse search does exist in current forward label
|
|
if(fwdOrRvsLabelMultimapIter !=
|
|
fwdOrRvsLabelMultimap.end())
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("potential witness access found" << endl);
|
|
#endif
|
|
std::tuple<int, int, double> currLabelTuple =
|
|
(*fwdOrRvsLabelMultimapIter).second;
|
|
double revDistSV =
|
|
std::get<HL_INDEX_OF_HUB_DISTANCE_TO_SOURCE_IN_LABEL_TUPLE
|
|
- 2>(currLabelTuple); //its -2 here because the
|
|
// multimap does not contain the hubTupleId usually
|
|
// on indexposition #3
|
|
|
|
if(revDistSV + revMinVDistToW <=
|
|
fwdDistSW) //XXTODO: auf kleiner oder kleiner-gleich
|
|
// prüfen? kleiner-gleich erzeugt kleinere labels,
|
|
// aber funktioniert der algorithmus dann noch?
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("witness found" << endl);
|
|
#endif
|
|
isPruned = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("scan new vertices" << endl);
|
|
#endif
|
|
if(hHop > revMinVHopDepth)
|
|
{
|
|
CcInt* revMinVNodeIDCcInt = new CcInt(true,
|
|
revMinVNodeID);
|
|
//zwingend per new erzeugen?
|
|
hlCreateLabelCheckForWitnessScanNewVertices(
|
|
reverseNotYetVisitedNodes, stillVisitedNodes,
|
|
edgesContractedUpwardsOrelSource,
|
|
edgesContractedDownwardsOrelTarget,
|
|
revMinVNodeIDCcInt, revMinVDistToW,
|
|
revMinVHopDepth, isForward);
|
|
revMinVNodeIDCcInt->DeleteIfAllowed(
|
|
true); //TODO: notwendig? bei getAttribute
|
|
// auch nicht notwendig
|
|
}
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlCreateLabelCheckForWitness" <<
|
|
endl);
|
|
#endif
|
|
return isPruned;
|
|
}
|
|
|
|
|
|
/*
|
|
* Scans for new vertices during dijkstra h-Hop reverse or
|
|
* forward search used to check the previously found node
|
|
* for a witness path in the opposite graph. see also
|
|
* hlCreateLabelCheckForWitness;
|
|
*
|
|
* @param reverseNotYetVisitedNodes is a Multimap by reference storing
|
|
* the vertices which are not yet visited by the h-hop reverse search
|
|
* @param reverseStillVisitedNodes is a vector by reference storing the
|
|
* vertices which are still visited by the h-hop reverse search
|
|
* @param edgesContractedUpwardsOrelSource is an OrderedRelation
|
|
* containging all edges of the underlying upwardsgraph sorted
|
|
* by the field Source
|
|
* @param edgesContractedDownwardsOrelTarget is an OrderedRelation
|
|
* containging all edges of the underlying downwardsgraph sorted
|
|
* by the field Target
|
|
* @param revGivenTargetIdV is the vertext ID of the current source
|
|
* node v which was chosen as next vertex to be scanned during
|
|
* h-hop reverse (or forward) search
|
|
* @param revGivenDistanceVToW contains the weighted distance from the
|
|
* original source w (of this reverse search) to the current given node v
|
|
* @param revGivenHopDepthV is a an integer representing the current
|
|
* hop-depth of the given node v
|
|
* @param isForward is a boolean that indicates whether a forward or
|
|
* reverselabel shall be created
|
|
* @return true since the result of this method is stored into
|
|
* reverseNotYetVisitedNodes
|
|
*/
|
|
bool hlCreateLabelCheckForWitnessScanNewVertices(
|
|
std::multimap<double, std::tuple<int, int>>
|
|
&reverseNotYetVisitedNodes,
|
|
std::vector<int> &reverseStillVisitedNodes,
|
|
OrderedRelation* edgesContractedUpwardsOrelSource,
|
|
OrderedRelation*
|
|
edgesContractedDownwardsOrelTarget,
|
|
CcInt* revGivenTargetIdV,
|
|
double revGivenDistanceVToW,
|
|
int revGivenHopDepthV, bool isForward) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Start hlCreateLabelCheckForWitnessScanNewVertices"
|
|
<< endl);
|
|
#endif
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("prepare iteration" << endl);
|
|
#endif
|
|
//iterate over all incoming edges (u, v)
|
|
// (on isForward = true search, vice versa else)
|
|
//Prepare Range scan
|
|
//Create From and to by revGivenTargetIdV (=v)
|
|
std::vector<void*> vecAttributesFromSourceV(1);
|
|
vecAttributesFromSourceV[0] = revGivenTargetIdV;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesFromSourceV(1);
|
|
vecAttrTypesFromSourceV[0] =
|
|
revGivenTargetIdV->getSMIKeyType();
|
|
CompositeKey fromSourceV(vecAttributesFromSourceV,
|
|
vecAttrTypesFromSourceV, false);
|
|
|
|
CcInt givenTargetIdVPlusOne(true,
|
|
revGivenTargetIdV->GetIntval() + 1);
|
|
CcInt* givenTargetIdVPlusOnePtr =
|
|
&givenTargetIdVPlusOne;
|
|
std::vector<void*> vecAttributesToSourceV(1);
|
|
vecAttributesToSourceV[0] =
|
|
givenTargetIdVPlusOnePtr;
|
|
std::vector<SmiKey::KeyDataType>
|
|
vecAttrTypesToSourceV(1);
|
|
vecAttrTypesToSourceV[0] =
|
|
givenTargetIdVPlusOnePtr->getSMIKeyType();
|
|
CompositeKey toSourceV(vecAttributesToSourceV,
|
|
vecAttrTypesToSourceV, false);
|
|
|
|
GenericRelationIterator*
|
|
reverseSearchEdgeOrelIter;
|
|
Tuple* currentReverseEdgeUV;
|
|
|
|
if(isForward)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("get incoming edges (u, v) within downwardsgraph"
|
|
<< endl);
|
|
#endif
|
|
reverseSearchEdgeOrelIter =
|
|
edgesContractedDownwardsOrelTarget->MakeRangeScan(
|
|
fromSourceV, toSourceV);
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("get outgoing edges (v, u) within upwardsgraph"
|
|
<< endl);
|
|
#endif
|
|
reverseSearchEdgeOrelIter =
|
|
edgesContractedUpwardsOrelSource->MakeRangeScan(
|
|
fromSourceV, toSourceV);
|
|
}
|
|
currentReverseEdgeUV =
|
|
reverseSearchEdgeOrelIter->GetNextTuple();
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("iterate and store incoming/outgoing egdes (u, v)/(v, u)"
|
|
" into reverseNotYetVisited"
|
|
<< endl);
|
|
#endif
|
|
while(currentReverseEdgeUV)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("next iteration witness scan new vertices"
|
|
<< endl);
|
|
#endif
|
|
|
|
//Get ID of current TargetNode (=x)
|
|
CcInt* currentTargetNodeX;
|
|
if(isForward)
|
|
{
|
|
//on isForward = true get source because its the
|
|
// reverse search here
|
|
currentTargetNodeX = (CcInt*)
|
|
currentReverseEdgeUV->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
}
|
|
else
|
|
{
|
|
currentTargetNodeX = (CcInt*)
|
|
currentReverseEdgeUV->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
}
|
|
|
|
if(std::find(reverseStillVisitedNodes.begin(),
|
|
reverseStillVisitedNodes.end(),
|
|
currentTargetNodeX->GetIntval()) ==
|
|
reverseStillVisitedNodes.end())
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("append tuple to reverseNotYet" << endl);
|
|
#endif
|
|
|
|
//create auxiliary data
|
|
std::tuple<double, int, int>
|
|
currParentNotYetMultimapTuple = std::make_tuple(
|
|
revGivenDistanceVToW,
|
|
revGivenTargetIdV->GetIntval(),
|
|
revGivenHopDepthV);
|
|
#ifdef USEDEBUG
|
|
LogDebug("insert or update" << endl);
|
|
#endif
|
|
//Either insert the new scanned W/V into not visited list
|
|
// or update it if it sill exists and has a shorter
|
|
// path via current v
|
|
bool isHHop = true;
|
|
hlInsertOrUpdateTupleInNotYetVisitedList(-1,
|
|
currParentNotYetMultimapTuple,
|
|
currentReverseEdgeUV, reverseNotYetVisitedNodes,
|
|
not isForward, isHHop);
|
|
#ifdef USEDEBUG
|
|
LogDebug("inserted or updated" << endl);
|
|
#endif
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get next tuple" << endl);
|
|
#endif
|
|
//Free Outgoing-Iteration
|
|
currentReverseEdgeUV->DeleteIfAllowed();
|
|
currentReverseEdgeUV = 0;
|
|
currentReverseEdgeUV =
|
|
reverseSearchEdgeOrelIter->GetNextTuple();
|
|
}
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish iteration" << endl);
|
|
#endif
|
|
|
|
//Free resources
|
|
delete reverseSearchEdgeOrelIter;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("end hlCreateLabelCheckForWitnessScanNewVertices"
|
|
<< endl);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Fully prunes the given label by running HL itself (bootstrapping),
|
|
* an OrderedRelation containing all labels (forward and reverse)
|
|
* for all nodes
|
|
* @param allLabelsOrel is an OrderedRelation containging all nodes of
|
|
* the underlying graph sorted by the field NodeIdNew
|
|
* @param currentForwardOrReverseLabel is an forward or reverse label
|
|
* @param currentSourceNode is the actual source node of the given
|
|
* forward or reverse label
|
|
* @param isForward is a boolean that indicates whether a forward or
|
|
* reverselabel shall be created
|
|
* @return an OrderedRelation containing all labels (forward and reverse)
|
|
* for all nodes within @see nodesRankedDescOrelRank
|
|
*/
|
|
bool hlPruneLabelByBootstrapping(OrderedRelation*
|
|
allLabelsOrel, OrderedRelation*
|
|
currentForwardOrReverseLabel,
|
|
CcInt* currentSourceNode, bool isForward) const
|
|
{
|
|
//Vector containing node ids to be deleted from
|
|
// orelXT after finishing full iteration
|
|
std::vector<int> hubsToDeleteVector;
|
|
|
|
GenericRelationIterator*
|
|
currentForwardOrReverseLabelIter =
|
|
currentForwardOrReverseLabel->MakeScan();
|
|
Tuple* currentHubTuple =
|
|
currentForwardOrReverseLabelIter->GetNextTuple();
|
|
|
|
while(currentHubTuple)
|
|
{
|
|
CcInt* currentHubId = (CcInt*)
|
|
currentHubTuple->GetAttribute(
|
|
HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE);
|
|
CcReal* currentHubDistance = (CcReal*)
|
|
currentHubTuple->GetAttribute(
|
|
HL_INDEX_OF_HUB_DISTANCE_TO_SOURCE_IN_LABEL_TUPLE);
|
|
CcReal* currentDistanceSourceToHub = new CcReal(
|
|
true, 0.0); //XXTODO mit richtiger Distance aus query füllen
|
|
//hlQuery(allLabelsOrel, currentSourceNode,
|
|
// currentHubId, isForward);
|
|
|
|
if(currentDistanceSourceToHub->GetRealval() <
|
|
currentHubDistance->GetRealval())
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Witness found by bootstrapping" << endl);
|
|
#endif
|
|
|
|
//prune this hub out
|
|
//Build list containing all hubs to be deleted
|
|
// later after iteration has finished
|
|
hubsToDeleteVector.push_back(
|
|
currentHubId->GetIntval());
|
|
}
|
|
|
|
currentHubTuple->DeleteIfAllowed();
|
|
currentHubTuple = 0;
|
|
currentHubTuple =
|
|
currentForwardOrReverseLabelIter->GetNextTuple();
|
|
}
|
|
#ifdef USEDEBUG
|
|
LogDebug("Free resources" << endl);
|
|
#endif
|
|
|
|
delete currentForwardOrReverseLabelIter;
|
|
|
|
for(std::vector<int>::iterator vecIter =
|
|
hubsToDeleteVector.begin();
|
|
vecIter != hubsToDeleteVector.end(); ++vecIter)
|
|
{
|
|
hlRemoveTuplesFromOrel(
|
|
currentForwardOrReverseLabel, *vecIter,
|
|
HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE); //TODO: ggf.
|
|
// rangescan in subfunktion ausführen um laufzeit zu sparen
|
|
}
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* XXTODO
|
|
*/
|
|
bool hlReorderLabels() const
|
|
{
|
|
//XXTODO
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Gets all edges by the given source and iterates over them searching
|
|
* for the given target.
|
|
* Returns the first edge-Tuple if found.
|
|
*
|
|
* @param currOrel
|
|
* @param sourceId
|
|
* @param targetId
|
|
* @return a new Tuple-Pointer
|
|
*/
|
|
Tuple* hlGetEdgeFromOrel(OrderedRelation* currOrel,
|
|
CcInt* sourceId, CcInt* targetId) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlGetEdgeFromOrel" << endl);
|
|
#endif
|
|
|
|
std::vector<void*> vecAttributesFrom(1);
|
|
vecAttributesFrom[0] = sourceId;
|
|
std::vector<SmiKey::KeyDataType> vecAttrTypesFrom(
|
|
1);
|
|
vecAttrTypesFrom[0] = sourceId->getSMIKeyType();
|
|
CompositeKey from(vecAttributesFrom,
|
|
vecAttrTypesFrom, false);
|
|
|
|
CcInt sourceIdPlusOne(true,
|
|
sourceId->GetIntval() + 1);
|
|
CcInt* sourceIdPlusOnePtr = &sourceIdPlusOne;
|
|
std::vector<void*> vecAttributesTo(1);
|
|
vecAttributesTo[0] = sourceIdPlusOnePtr;
|
|
std::vector<SmiKey::KeyDataType> vecAttrTypesTo(
|
|
1);
|
|
vecAttrTypesTo[0] =
|
|
sourceIdPlusOnePtr->getSMIKeyType();
|
|
CompositeKey to(vecAttributesTo, vecAttrTypesTo,
|
|
false);
|
|
|
|
GenericRelationIterator* currOrelIter =
|
|
currOrel->MakeRangeScan(from, to);
|
|
Tuple* currTuple = currOrelIter->GetNextTuple();
|
|
|
|
while(currTuple)
|
|
{
|
|
CcInt* currTargetId = (CcInt*) currTuple->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
|
|
if(currTargetId->GetIntval() == targetId->GetIntval())
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("tupleFound, break" << endl);
|
|
#endif
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
currTuple->DeleteIfAllowed();
|
|
currTuple = 0;
|
|
currTuple = currOrelIter->GetNextTuple();
|
|
}
|
|
}
|
|
delete currOrelIter;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlGetEdgeFromOrel" << endl);
|
|
#endif
|
|
return currTuple;
|
|
}
|
|
|
|
/*
|
|
* Gets an shortcut edge tuple and retrieves its both parent edges
|
|
* If one of the parent-edges are also shortcuts,
|
|
* the function itself is called recursively for it.
|
|
*
|
|
* @param edgesOrelSource the orel containing all edges including shortcuts
|
|
* @param currEdge the current edge to be resolved
|
|
* @param currPath the vector where all original edges resolved shall
|
|
* be stored into
|
|
* @param isForward indicates whether we perform the forward or reverse
|
|
* label, used for input order of shortcut-parts
|
|
* @return true since the result of this operator is stored into currPath
|
|
*/
|
|
bool hlResolveShortcuts(OrderedRelation* edgesOrelSource, Tuple* currEdge,
|
|
std::vector<Tuple*> &currPath, bool isForward) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlResolveShortcuts" << endl);
|
|
#endif
|
|
|
|
//Get parameters of currEdge
|
|
CcInt* sourceId = (CcInt*) currEdge->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
CcInt* targetId = (CcInt*) currEdge->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
|
|
//get parentId from current edgeTuple
|
|
CcInt* parentId = (CcInt*) currEdge->GetAttribute(
|
|
HL_INDEX_OF_PARENT_ID_IN_EDGE_TUPLE);
|
|
|
|
Tuple* parentTuple = 0;
|
|
|
|
//check whether curr Edge is shortcut
|
|
if(parentId->GetIntval() > -1)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("source: " << sourceId->GetIntval() <<
|
|
" parent: " << parentId->GetIntval() <<
|
|
" target: " << targetId->GetIntval() <<
|
|
" is shortcut, doing recursive call" << endl);
|
|
#endif
|
|
if(isForward)
|
|
{
|
|
//reverse insert because we will reverse output them because
|
|
// we handle forward label here
|
|
// (which means that we are inserting the hub first, then its
|
|
// parents and the source last
|
|
#ifdef USEDEBUG
|
|
LogDebug("edge from parent: " <<
|
|
parentId->GetIntval() << " to target: " <<
|
|
targetId->GetIntval() << endl);
|
|
#endif
|
|
parentTuple = hlGetEdgeFromOrel(edgesOrelSource,
|
|
parentId, targetId);
|
|
hlResolveShortcuts(edgesOrelSource, parentTuple,
|
|
currPath, isForward);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("edge from source: " <<
|
|
sourceId->GetIntval() << " to parent: " <<
|
|
parentId->GetIntval() << endl);
|
|
#endif
|
|
parentTuple = hlGetEdgeFromOrel(edgesOrelSource,
|
|
sourceId, parentId);
|
|
hlResolveShortcuts(edgesOrelSource, parentTuple,
|
|
currPath, isForward);
|
|
|
|
}
|
|
else
|
|
{
|
|
//vice versa as forward
|
|
#ifdef USEDEBUG
|
|
LogDebug("edge from source: " <<
|
|
sourceId->GetIntval() << " to parent: " <<
|
|
parentId->GetIntval() << endl);
|
|
#endif
|
|
parentTuple = hlGetEdgeFromOrel(edgesOrelSource,
|
|
sourceId, parentId);
|
|
hlResolveShortcuts(edgesOrelSource, parentTuple,
|
|
currPath, isForward);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("edge from parent: " <<
|
|
parentId->GetIntval() << " to target: " <<
|
|
targetId->GetIntval() << endl);
|
|
#endif
|
|
parentTuple = hlGetEdgeFromOrel(edgesOrelSource,
|
|
parentId, targetId);
|
|
hlResolveShortcuts(edgesOrelSource, parentTuple,
|
|
currPath, isForward);
|
|
}
|
|
|
|
currEdge->DeleteIfAllowed();
|
|
currEdge = 0;
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("is original Edge, pushback into path-vector" << endl);
|
|
#endif
|
|
currPath.push_back(currEdge);
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlResolveShortcuts" << endl);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Gets an shortcut edge tuple and retrieves its both parent edges
|
|
* If one of the parent-edges are also shortcuts,
|
|
* the function itself is called recursively for it.
|
|
*
|
|
* @param edgesOrelSource the orel containing all edges but not shortcuts
|
|
* @param hlGraph the orel representing the hlGraph
|
|
* @param sourceNodeId the sourceNodeId
|
|
* @param targetNodeId the targetNodeId
|
|
* @param currPath the vector where all original edges resolved shall
|
|
* be stored into
|
|
* @param isForward indicates whether we perform the forward or reverse
|
|
* label, used for input order of shortcut-parts
|
|
* @param isUpward indicates whether we perform an upward or downward edge
|
|
* @return true since the result of this operator is stored into currPath
|
|
*/
|
|
bool hlResolveShortcutsHlGraph(OrderedRelation* edgesOrelSource,
|
|
OrderedRelation* hlGraph, CcInt* sourceNodeId, CcInt* targetNodeId,
|
|
std::vector<Tuple*> &currPath, bool isForward, bool isUpward) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlResolveShortcutsHlGraph" << endl);
|
|
#endif
|
|
|
|
Tuple* currHlGraphEdge = hlGetEdgeFromOrel(hlGraph,
|
|
sourceNodeId, targetNodeId);
|
|
|
|
//get parentId from current edgeTuple
|
|
int currFieldIndex = -1;
|
|
if(isUpward)
|
|
{
|
|
currFieldIndex = HL_INDEX_OF_PARENT_ID_FORWARD_IN_HL_GRAPH;
|
|
}else{
|
|
currFieldIndex = HL_INDEX_OF_PARENT_ID_REVERSE_IN_HL_GRAPH;
|
|
}
|
|
CcInt* parentNodeId =
|
|
(CcInt*) currHlGraphEdge->GetAttribute(currFieldIndex);
|
|
|
|
//check whether curr Edge is shortcut
|
|
if(parentNodeId->GetIntval() > -1)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("source: " << sourceNodeId->GetIntval() <<
|
|
" parent: " << parentNodeId->GetIntval() <<
|
|
" target: " << targetNodeId->GetIntval() <<
|
|
" is shortcut, doing recursive call" << endl);
|
|
#endif
|
|
|
|
//there are four cases
|
|
// 1) isForwardLabel and isUpwardEdge
|
|
// 2) isForwardLabel and not isUpwardEdge
|
|
// 3) not isForwardLabel and not isUpwardEdge
|
|
// 4) not isForwardLabel and isUpwardEdge
|
|
//
|
|
// in case of 1) and 2) we want sub-edges parent->target
|
|
// before parent->source
|
|
if(isUpward == isForward)
|
|
{
|
|
//first process edge from parent to target
|
|
// second process edge from parent to souce
|
|
// is valid for both forward and reverse processing
|
|
#ifdef USEDEBUG
|
|
LogDebug("next is edge from parent: " <<
|
|
parentNodeId->GetIntval() << " to target: " <<
|
|
targetNodeId->GetIntval() << endl);
|
|
#endif
|
|
hlResolveShortcutsHlGraph(edgesOrelSource, hlGraph,
|
|
parentNodeId, targetNodeId, currPath, isForward, isUpward);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("next is edge from parent: " <<
|
|
parentNodeId->GetIntval() << " to source: " <<
|
|
sourceNodeId->GetIntval() << endl);
|
|
#endif
|
|
hlResolveShortcutsHlGraph(edgesOrelSource, hlGraph,
|
|
parentNodeId, sourceNodeId, currPath, isForward, !isUpward);
|
|
}
|
|
else
|
|
{
|
|
//vice versa as upward
|
|
#ifdef USEDEBUG
|
|
LogDebug("edge from parent: " <<
|
|
parentNodeId->GetIntval() << " to source: " <<
|
|
sourceNodeId->GetIntval() << endl);
|
|
#endif
|
|
hlResolveShortcutsHlGraph(edgesOrelSource, hlGraph,
|
|
parentNodeId, sourceNodeId, currPath, isForward, !isUpward);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("edge from parent: " <<
|
|
parentNodeId->GetIntval() << " to target: " <<
|
|
targetNodeId->GetIntval() << endl);
|
|
#endif
|
|
hlResolveShortcutsHlGraph(edgesOrelSource, hlGraph,
|
|
parentNodeId, targetNodeId, currPath, isForward, isUpward);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("is original Edge, pushback into path-vector" << endl);
|
|
#endif
|
|
|
|
//get edge from edgesOrelSource
|
|
// originalEdge only matches with current source/ target if
|
|
// isUpwardEdge
|
|
Tuple* currOriginalEdge = 0;
|
|
if(isUpward)
|
|
{
|
|
currOriginalEdge = hlGetEdgeFromOrel(edgesOrelSource,
|
|
sourceNodeId, targetNodeId);
|
|
}else{
|
|
currOriginalEdge = hlGetEdgeFromOrel(edgesOrelSource,
|
|
targetNodeId, sourceNodeId);
|
|
}
|
|
|
|
|
|
currPath.push_back(currOriginalEdge);
|
|
}
|
|
|
|
currHlGraphEdge->DeleteIfAllowed();
|
|
currHlGraphEdge = 0;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlResolveShortcutsHlGraph" << endl);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Function traversing from the given hup to all its parents back to
|
|
* the source or target (on reverse-hub)
|
|
* Also resolves shortcuts by temporal creating edges on the path build
|
|
* up and find the
|
|
* corresponding edges within the Edges-Relation containing also shortcuts.
|
|
* Inserts all original nodes represented by this shortcut and its
|
|
* underlying shortcuts
|
|
* also into the path-vector
|
|
* After resolving a shortcut it comes back to the basic iteration over
|
|
* all parents of the hub.
|
|
* @param edgesWithShortcutsOrelSource is an OrderedRelation containing
|
|
* all edges including shortcuts
|
|
* @param dataRel is the Relation containing all data-tuples of the
|
|
* forward- and reverse labels
|
|
* @param currHub is an Tuple representing the current hub for whichs
|
|
* parent a recursive call is made
|
|
* @param path is a vector used to store all edges on the way from source
|
|
* to the hub
|
|
* @param isForward is a boolean to indicate whether the path shall be
|
|
* retrieved from a forward or reverse Label
|
|
* @return true, since the result ist stored in path
|
|
*/
|
|
bool hlGetPathViaPoints(OrderedRelation* edgesWithShortcutsOrelSource,
|
|
Relation* dataRel, Tuple* givenHubTuple,
|
|
std::vector<Tuple*> &path, bool isForward) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlGetPathViaPoints" << endl);
|
|
#endif
|
|
|
|
bool isFinished = false;
|
|
Tuple* currTuple = givenHubTuple;
|
|
|
|
while(!isFinished)
|
|
{
|
|
CcInt* currTupleNodeId = (CcInt*) currTuple->GetAttribute(
|
|
HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE);
|
|
CcInt* currTupleParentTupleId = (CcInt*) currTuple->GetAttribute(
|
|
HL_INDEX_OF_HUB_PARENT_TUPLE_ID_IN_LABEL_TUPLE);
|
|
|
|
#ifdef USEDEBUG
|
|
CcInt* currTupleNodeIdNew = (CcInt*) currTuple->GetAttribute(
|
|
HL_INDEX_OF_HUB_NODE_ID_NEW_IN_LABEL_TUPLE);
|
|
LogDebug("current tuple rank: " <<
|
|
currTupleNodeIdNew->GetIntval() << " nodeId: " <<
|
|
currTupleNodeId->GetIntval() << endl);
|
|
#endif
|
|
|
|
if(currTupleParentTupleId->GetIntval() > -1)
|
|
{
|
|
TupleId currParentTupleId =
|
|
(TupleId) currTupleParentTupleId->GetIntval();
|
|
Tuple* currParentTuple =
|
|
dataRel->GetTuple(currParentTupleId, false);
|
|
|
|
if(!currParentTuple)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Fehler, Tuple aus dataRel ist null mit TupleId: "
|
|
<< currParentTupleId << endl);
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
CcInt* currParentNodeId =
|
|
(CcInt*) currParentTuple->GetAttribute(
|
|
HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE);
|
|
#ifdef USEDEBUG
|
|
LogDebug("curr parentNodeId: " <<
|
|
currParentNodeId->GetIntval() <<
|
|
" parentTupleid: " << currParentTupleId << endl);
|
|
#endif
|
|
|
|
//get current Edge
|
|
Tuple* currEdge = 0;
|
|
CcInt* currSourceId = 0;
|
|
CcInt* currTargetId = 0;
|
|
if(isForward)
|
|
{
|
|
currSourceId = currParentNodeId;
|
|
currTargetId = currTupleNodeId;
|
|
}
|
|
else
|
|
{
|
|
currSourceId = currTupleNodeId;
|
|
currTargetId = currParentNodeId;
|
|
}
|
|
|
|
currEdge = hlGetEdgeFromOrel(edgesWithShortcutsOrelSource,
|
|
currSourceId, currTargetId);
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("resolve shortcuts for source: " <<
|
|
currSourceId->GetIntval() << " target: " <<
|
|
currTargetId->GetIntval() << endl);
|
|
#endif
|
|
|
|
hlResolveShortcuts(edgesWithShortcutsOrelSource,
|
|
currEdge, path, isForward);
|
|
|
|
currTuple->DeleteIfAllowed();
|
|
currTuple = 0;
|
|
currTuple = currParentTuple;
|
|
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("endpoint found exit" << endl);
|
|
#endif
|
|
|
|
currTuple->DeleteIfAllowed();
|
|
currTuple = 0;
|
|
isFinished = true;
|
|
}
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlGetPathViaPoints" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Function traversing from the given hup to all its parents back to
|
|
* the source or target (on reverse-hub)
|
|
* Also resolves shortcuts by temporal creating edges on the path build
|
|
* up and find the
|
|
* corresponding edges within the Edges-Relation containing also shortcuts.
|
|
* Inserts all original nodes represented by this shortcut and its
|
|
* underlying shortcuts
|
|
* also into the path-vector
|
|
* After resolving a shortcut it comes back to the basic iteration over
|
|
* all parents of the hub.
|
|
* @param edgesOrelSource is an OrderedRelation containing
|
|
* all original edges but not shortcuts
|
|
* @param hlGraphOrel is an OrderedRelation representing the hlGraph
|
|
* @param dataRel is the Relation containing all data-tuples of the
|
|
* forward- and reverse labels
|
|
* @param currHub is an Tuple representing the current hub for whichs
|
|
* parent a recursive call is made
|
|
* @param path is a vector used to store all edges on the way from source
|
|
* to the hub
|
|
* @param isForward is a boolean to indicate whether the path shall be
|
|
* retrieved from a forward or reverse Label
|
|
* @return true, since the result ist stored in path
|
|
*/
|
|
bool hlGetPathViaPointsHlGraph(OrderedRelation* edgesOrelSource,
|
|
OrderedRelation* hlGraphOrel,
|
|
Relation* dataRel, Tuple* givenHubTuple,
|
|
std::vector<Tuple*> &path, bool isForward) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlGetPathViaPointsHlGraph" << endl);
|
|
#endif
|
|
|
|
bool isFinished = false;
|
|
Tuple* currTuple = givenHubTuple;
|
|
|
|
while(!isFinished)
|
|
{
|
|
CcInt* currTupleNodeId = (CcInt*) currTuple->GetAttribute(
|
|
HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE);
|
|
CcInt* currTupleParentTupleId = (CcInt*) currTuple->GetAttribute(
|
|
HL_INDEX_OF_HUB_PARENT_TUPLE_ID_IN_LABEL_TUPLE);
|
|
|
|
#ifdef USEDEBUG
|
|
CcInt* currTupleNodeIdNew = (CcInt*) currTuple->GetAttribute(
|
|
HL_INDEX_OF_HUB_NODE_ID_NEW_IN_LABEL_TUPLE);
|
|
LogDebug("current tuple rank: " <<
|
|
currTupleNodeIdNew->GetIntval() << " nodeId: " <<
|
|
currTupleNodeId->GetIntval() << endl);
|
|
#endif
|
|
|
|
if(currTupleParentTupleId->GetIntval() > -1)
|
|
{
|
|
TupleId currParentTupleId =
|
|
(TupleId) currTupleParentTupleId->GetIntval();
|
|
Tuple* currParentTuple =
|
|
dataRel->GetTuple(currParentTupleId, false);
|
|
|
|
if(!currParentTuple)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Fehler, Tuple aus dataRel ist null mit TupleId: "
|
|
<< currParentTupleId << endl);
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
CcInt* currParentNodeId =
|
|
(CcInt*) currParentTuple->GetAttribute(
|
|
HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE);
|
|
#ifdef USEDEBUG
|
|
LogDebug("curr parentNodeId: " <<
|
|
currParentNodeId->GetIntval() <<
|
|
" parentTupleid: " << currParentTupleId << endl);
|
|
#endif
|
|
|
|
//get current Edge
|
|
CcInt* currSourceId = 0;
|
|
CcInt* currTargetId = 0;
|
|
|
|
//in both cases of forward and reverse Label
|
|
// we need to get edges in upward manner
|
|
// which means currTuple always is target
|
|
// and currParent is always source
|
|
currSourceId = currParentNodeId;
|
|
currTargetId = currTupleNodeId;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("resolve shortcuts for source: " <<
|
|
currSourceId->GetIntval() << " target: " <<
|
|
currTargetId->GetIntval() << endl);
|
|
#endif
|
|
|
|
hlResolveShortcutsHlGraph(edgesOrelSource, hlGraphOrel,
|
|
currSourceId, currTargetId, path, isForward, isForward);
|
|
|
|
currTuple->DeleteIfAllowed();
|
|
currTuple = 0;
|
|
currTuple = currParentTuple;
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("endpoint found exit" << endl);
|
|
#endif
|
|
|
|
currTuple->DeleteIfAllowed();
|
|
currTuple = 0;
|
|
isFinished = true;
|
|
}
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlGetPathViaPointsHlGraph" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Searches for the shortest path from the given sourceNodeId to
|
|
* the given targetNodeId
|
|
* and stores the path with all its via-points into the given relation
|
|
* shortestPath
|
|
* where the nodes are stored in the order of the path going from source
|
|
* to target.
|
|
* @param allLabelsNRel is NestedList containing all Labels
|
|
* @param allLabelsBTree is BTree over the NestedRelation containging
|
|
* all Labels of all nodes
|
|
* @param edgesWithShortcutsOrelSource is an OrderedRelation containing
|
|
* all edges including shortcuts (does not contain shortcuts in case
|
|
* of isHlGraph == true)
|
|
* @param hlGraphOrel is an OrderedRelation containing
|
|
* the hlGraph or null if not isHlGraph == true
|
|
* @param shortestPath is an Relation representing the result of this
|
|
* function
|
|
* @param sourceNodeId is the actual source node of the given forward or
|
|
* reverse label
|
|
* @param targetNodeId is a boolean that indicates whether a forward or
|
|
* reverselabel shall be created
|
|
* @param isHlGraph indicates whether we are in (1) old logic or
|
|
* (2) new logic using hlGraph
|
|
* @return true, since the result ist stored in shortestPath
|
|
*/
|
|
bool hlQuery(NestedRelation* allLabelsNRel, BTree* allLabelsBTree,
|
|
OrderedRelation* edgesWithShortcutsOrelSource,
|
|
OrderedRelation* hlGraphOrel, Relation* shortestPath,
|
|
CcInt* sourceNodeId, CcInt* targetNodeId, bool isHlGraph) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlQuery" << endl);
|
|
#endif
|
|
|
|
#ifdef USEPERF
|
|
double perfTime = getCurrentTimeInMs();
|
|
double perfTime2 = 0.0;
|
|
double perfTime3 = 0.0;
|
|
#endif
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get btree iterator by source: " <<
|
|
sourceNodeId->GetIntval() << " target: " <<
|
|
targetNodeId->GetIntval() << endl);
|
|
#endif
|
|
|
|
BTreeIterator* bTreeSourceIter =
|
|
allLabelsBTree->ExactMatch(sourceNodeId);
|
|
BTreeIterator* bTreeTargetIter =
|
|
allLabelsBTree->ExactMatch(targetNodeId);
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get next tuple from btree forward" <<
|
|
endl);
|
|
#endif
|
|
|
|
int tupleIdSourceInt = -1;
|
|
int tupleIdTargetInt = -1;
|
|
|
|
if(bTreeSourceIter)
|
|
{
|
|
if(bTreeSourceIter->Next())
|
|
{
|
|
tupleIdSourceInt = bTreeSourceIter->GetId();
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Fehler: kein Tuple in BTree für Source enthalten,"
|
|
" breche Anfrage ab"
|
|
<< endl);
|
|
#endif
|
|
return false;
|
|
}
|
|
delete bTreeSourceIter;
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Fehler: sourceNode wurde nicht in Labels gefunden,"
|
|
" breche Anfrage ab"
|
|
<< endl);
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get next tuple from btree reverse" <<
|
|
endl);
|
|
#endif
|
|
|
|
if(bTreeTargetIter)
|
|
{
|
|
if(bTreeTargetIter->Next())
|
|
{
|
|
tupleIdTargetInt = bTreeTargetIter->GetId();
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Fehler: kein Tuple in BTree für Target enthalten,"
|
|
" breche Anfrage ab"
|
|
<< endl);
|
|
#endif
|
|
return false;
|
|
}
|
|
delete bTreeTargetIter;
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Fehler: targetNode wurde nicht in Labels gefunden,"
|
|
" breche Anfrage ab"
|
|
<< endl);
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("create TupleIds and get primary" << endl);
|
|
#endif
|
|
|
|
TupleId tupleIdSource = (TupleId) tupleIdSourceInt;
|
|
TupleId tupleIdTarget = (TupleId) tupleIdTargetInt;
|
|
|
|
Relation* primary = allLabelsNRel->getPrimary();
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get tuple from primary" << endl);
|
|
#endif
|
|
|
|
//gets tuplepointers created by new
|
|
Tuple* tupleSource = primary->GetTuple(tupleIdSource, false);
|
|
Tuple* tupleTarget = primary->GetTuple(tupleIdTarget, false);
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get arel from tupleId " << endl);
|
|
#endif
|
|
|
|
AttributeRelation* attrRelSource =
|
|
(AttributeRelation*) tupleSource->GetAttribute(
|
|
HL_INDEX_OF_FORWARD_LABEL_IN_ALL_LABELS_TUPLE);
|
|
AttributeRelation* attrRelTarget =
|
|
(AttributeRelation*) tupleTarget->GetAttribute(
|
|
HL_INDEX_OF_REVERSE_LABEL_IN_ALL_LABELS_TUPLE);
|
|
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get subrel from nrel" << endl);
|
|
#endif
|
|
|
|
SubRelation* dataSubRelForward =
|
|
allLabelsNRel->getSubRel(
|
|
hlForwardLabelColumnName());
|
|
SubRelation* dataSubRelReverse =
|
|
allLabelsNRel->getSubRel(
|
|
hlReverseLabelColumnName());
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get datarel from subrel" << endl);
|
|
#endif
|
|
|
|
Relation* dataRelForward = dataSubRelForward->rel;
|
|
Relation* dataRelReverse = dataSubRelReverse->rel;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get tupleids from arels" << endl);
|
|
#endif
|
|
|
|
DbArray<TupleId>* tupleIdsForward =
|
|
attrRelSource->getTupleIds();
|
|
DbArray<TupleId>* tupleIdsReverse =
|
|
attrRelTarget->getTupleIds();
|
|
|
|
TupleId tidForward;
|
|
TupleId tidReverse;
|
|
|
|
int indexForward = 0;
|
|
int indexReverse = 0;
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get tuple id for data rel from dbarray" <<
|
|
endl);
|
|
#endif
|
|
|
|
//XXTODO: TupleId hier kein Zeiger?
|
|
tupleIdsForward->Get(indexForward, tidForward);
|
|
//XXTODO: TupleId hier kein Zeiger?
|
|
tupleIdsReverse->Get(indexReverse, tidReverse);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("get tuples from datarel" << endl);
|
|
#endif
|
|
|
|
//XXTODO: TupleId hier kein Zeiger?
|
|
Tuple* currTupleDataRelSource =
|
|
dataRelForward->GetTuple(tidForward, false);
|
|
//XXTODO: TupleId hier kein Zeiger?
|
|
Tuple* currTupleDataRelTarget =
|
|
dataRelReverse->GetTuple(tidReverse, false);
|
|
|
|
|
|
Tuple* currMinHubSource = 0;
|
|
Tuple* currMinHubTarget = 0;
|
|
|
|
double currMinDist = -1.0;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("parallel sweep" << endl);
|
|
#endif
|
|
|
|
//usually breaks when tupleId-arrays reach end of index
|
|
while(currTupleDataRelSource &&
|
|
currTupleDataRelTarget)
|
|
{
|
|
//get HubNodeIds of both Iterators
|
|
CcInt* currHubNodeIdNewSource =
|
|
(CcInt*) currTupleDataRelSource->GetAttribute(
|
|
HL_INDEX_OF_HUB_NODE_ID_NEW_IN_LABEL_TUPLE);
|
|
CcInt* currHubNodeIdNewTarget =
|
|
(CcInt*) currTupleDataRelTarget->GetAttribute(
|
|
HL_INDEX_OF_HUB_NODE_ID_NEW_IN_LABEL_TUPLE);
|
|
|
|
|
|
if(currHubNodeIdNewSource->GetIntval() ==
|
|
currHubNodeIdNewTarget->GetIntval())
|
|
{
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("source and target are equal: " <<
|
|
currHubNodeIdNewSource->GetIntval() << endl);
|
|
#endif
|
|
|
|
//get distances of both iterators
|
|
CcReal* currHubDistToSource = (CcReal*)
|
|
currTupleDataRelSource->GetAttribute(
|
|
HL_INDEX_OF_HUB_DISTANCE_TO_SOURCE_IN_LABEL_TUPLE);
|
|
CcReal* currHubDistToTarget = (CcReal*)
|
|
currTupleDataRelTarget->GetAttribute(
|
|
HL_INDEX_OF_HUB_DISTANCE_TO_SOURCE_IN_LABEL_TUPLE);
|
|
|
|
//Check for shorter path
|
|
double currMinDistTmp =
|
|
currHubDistToSource->GetRealval() +
|
|
currHubDistToTarget->GetRealval();
|
|
if(currMinDist == -1.0 ||
|
|
currMinDistTmp < currMinDist)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("new min found: " << currMinDistTmp << endl);
|
|
#endif
|
|
currMinDist = currMinDistTmp;
|
|
|
|
if(currMinHubSource)
|
|
{
|
|
//delete previous stored tuples for later use
|
|
currMinHubSource->DeleteIfAllowed();
|
|
}
|
|
//save new tuple with minimum distance for later use
|
|
currMinHubSource = currTupleDataRelSource;
|
|
|
|
|
|
if(currMinHubTarget)
|
|
{
|
|
//delete previous stored tuples for later use
|
|
currMinHubTarget->DeleteIfAllowed();
|
|
}
|
|
//save new tuple with minimum distance for later use
|
|
currMinHubTarget = currTupleDataRelTarget;
|
|
|
|
//dont delete current Tuples from interators,
|
|
// they are stored for later use
|
|
//currTupleDataRelSource = 0; //XXTODO: wäre das
|
|
// richtig oder sogar schlimm? oder egal?
|
|
//currTupleDataRelTarget = 0;
|
|
}
|
|
else
|
|
{
|
|
//delete current Tuples from iterators
|
|
currTupleDataRelSource->DeleteIfAllowed();
|
|
currTupleDataRelSource = 0;
|
|
currTupleDataRelTarget->DeleteIfAllowed();
|
|
currTupleDataRelTarget = 0;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("increase both" << endl);
|
|
#endif
|
|
|
|
//increase both iterators
|
|
indexForward++;
|
|
indexReverse++;
|
|
|
|
if(tupleIdsForward->Size() > indexForward)
|
|
{
|
|
tupleIdsForward->Get(indexForward, tidForward);
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("end of Array tupleIdsForward reached (size: "
|
|
<< tupleIdsForward->Size() << " currIndex: " <<
|
|
indexForward << "), breaking loop" << endl);
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
if(tupleIdsReverse->Size() > indexReverse)
|
|
{
|
|
tupleIdsReverse->Get(indexReverse, tidReverse);
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("end of Array tupleIdsReverse reached (size: "
|
|
<< tupleIdsReverse->Size() << " currIndex: " <<
|
|
indexReverse << "), breaking loop" << endl);
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("increase both - set next tuples. forward: "
|
|
<< tidForward << " reverse: " << tidReverse <<
|
|
endl);
|
|
#endif
|
|
|
|
currTupleDataRelSource = dataRelForward->GetTuple(
|
|
tidForward, false);
|
|
currTupleDataRelTarget = dataRelReverse->GetTuple(
|
|
tidReverse, false);
|
|
}
|
|
else if(currHubNodeIdNewSource->GetIntval() <
|
|
currHubNodeIdNewTarget->GetIntval())
|
|
{
|
|
//increase forward iterator
|
|
currTupleDataRelSource->DeleteIfAllowed();
|
|
currTupleDataRelSource = 0;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("increase forward" << endl);
|
|
#endif
|
|
|
|
indexForward++;
|
|
|
|
if(tupleIdsForward->Size() > indexForward)
|
|
{
|
|
tupleIdsForward->Get(indexForward, tidForward);
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("end of Array tupleIdsForward reached (size: "
|
|
<< tupleIdsForward->Size() << " currIndex: " <<
|
|
indexForward << "), breaking loop" << endl);
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("increase forward - set next tuple. forward: "
|
|
<< tidForward << endl);
|
|
#endif
|
|
currTupleDataRelSource = dataRelForward->GetTuple(
|
|
tidForward, false);
|
|
//XXTODO: TupleId hier kein Zeiger?
|
|
}
|
|
else
|
|
{
|
|
//increase reverse iterator
|
|
currTupleDataRelTarget->DeleteIfAllowed();
|
|
currTupleDataRelTarget = 0;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("increase reverse" << endl);
|
|
#endif
|
|
|
|
indexReverse++;
|
|
|
|
if(tupleIdsReverse->Size() > indexReverse)
|
|
{
|
|
tupleIdsReverse->Get(indexReverse, tidReverse);
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("end of Array tupleIdsReverse reached (size: "
|
|
<< tupleIdsReverse->Size() << " currIndex: " <<
|
|
indexReverse << "), breaking loop" << endl);
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("increase reverse - set next tuple. reverse: "
|
|
<< tidReverse << endl);
|
|
#endif
|
|
currTupleDataRelTarget =
|
|
dataRelReverse->GetTuple(tidReverse, false);
|
|
//XXTODO: TupleId hier kein Zeiger?
|
|
}
|
|
}
|
|
|
|
tupleSource->DeleteIfAllowed();
|
|
tupleTarget->DeleteIfAllowed();
|
|
|
|
#ifdef USEPERF
|
|
perfTime2 = getCurrentTimeInMs();
|
|
LogPerf("perf: duration of actual hl search: (ms) "
|
|
<< fixed << (perfTime2 - perfTime) << endl);
|
|
#endif
|
|
|
|
std::vector<Tuple*> pathForward;
|
|
std::vector<Tuple*> pathReverse;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("lookup paths" << endl);
|
|
#endif
|
|
|
|
if(currMinHubSource)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("get PathVia for currMinHubSource" << endl);
|
|
#endif
|
|
|
|
//differ between (1) old logic and (2) new logic
|
|
if(isHlGraph)
|
|
{
|
|
hlGetPathViaPointsHlGraph(edgesWithShortcutsOrelSource,
|
|
hlGraphOrel, dataRelForward, currMinHubSource,
|
|
pathForward, true);
|
|
}else{
|
|
hlGetPathViaPoints(edgesWithShortcutsOrelSource,
|
|
dataRelForward, currMinHubSource, pathForward, true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Warnung, Tuple currMinHubSource ist null, fahre fort"
|
|
<< endl);
|
|
#endif
|
|
}
|
|
if(currMinHubTarget)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("get PathVia for currMinHubTarget" << endl);
|
|
#endif
|
|
|
|
if(isHlGraph)
|
|
{
|
|
hlGetPathViaPointsHlGraph(edgesWithShortcutsOrelSource,
|
|
hlGraphOrel, dataRelReverse, currMinHubTarget,
|
|
pathReverse, false);
|
|
}else{
|
|
hlGetPathViaPoints(edgesWithShortcutsOrelSource,
|
|
dataRelReverse, currMinHubTarget, pathReverse, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Warnung, Tuple currMinHubTarget ist null, fahre fort"
|
|
<< endl);
|
|
#endif
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("iterate forward path" << endl);
|
|
#endif
|
|
|
|
//Reverse-Iterate through pathForward and add edges
|
|
// (source and target) to shortestPath
|
|
for (std::vector<Tuple*>::reverse_iterator
|
|
pathForwardIterReverse = pathForward.rbegin();
|
|
pathForwardIterReverse != pathForward.rend();
|
|
++pathForwardIterReverse )
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("insert next edge" << endl);
|
|
#endif
|
|
Tuple* currEdge = *(pathForwardIterReverse);
|
|
|
|
#ifdef USEDEBUG
|
|
CcInt* sourceTmp = (CcInt*)
|
|
currEdge->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
CcInt* targetTmp = (CcInt*)
|
|
currEdge->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
LogDebug("append tuple forward: source = " <<
|
|
sourceTmp->GetIntval() << " target: " <<
|
|
targetTmp->GetIntval() << endl);
|
|
#endif
|
|
|
|
shortestPath->AppendTuple(currEdge);
|
|
currEdge->DeleteIfAllowed();
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("iterate reverse path" << endl);
|
|
#endif
|
|
|
|
//forward iterate through pathReverse and add it to shortestPath
|
|
for (std::vector<Tuple*>::iterator pathReverseIter
|
|
= pathReverse.begin();
|
|
pathReverseIter != pathReverse.end();
|
|
++pathReverseIter)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("insert next edge" << endl);
|
|
#endif
|
|
Tuple* currEdge = *(pathReverseIter);
|
|
|
|
#ifdef USEDEBUG
|
|
CcInt* sourceTmp = (CcInt*)
|
|
currEdge->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
CcInt* targetTmp = (CcInt*)
|
|
currEdge->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
LogDebug("append tuple reverse: source = " <<
|
|
sourceTmp->GetIntval() << " target: " <<
|
|
targetTmp->GetIntval() << endl);
|
|
#endif
|
|
|
|
shortestPath->AppendTuple(currEdge);
|
|
currEdge->DeleteIfAllowed();
|
|
}
|
|
|
|
#ifdef USEPERF
|
|
perfTime3 = getCurrentTimeInMs();
|
|
LogPerf("perf: duration of resolving shortest path: (ms) "
|
|
<< fixed << (perfTime3 - perfTime2) << endl);
|
|
#endif
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlQuery" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
3.3 HubLabeling functionality of (2) In-Memory Approach
|
|
|
|
*/
|
|
/*
|
|
* OrderedRelation type for a set of Nodes contained within the hlGraph
|
|
* Used for creation of new OrderedRelation Objects, new Tuples of
|
|
* this OrderedRelation or cloning or deleting of an
|
|
* OrderedRelation of this type
|
|
*/
|
|
static const string hlGetHlGraphNodesOrelTypeInfo()
|
|
{
|
|
return "(" + OrderedRelation::BasicType() +
|
|
hlGetHlGraphNodesTupleTypeInfo() +
|
|
"(Source)" +
|
|
")";
|
|
}
|
|
|
|
|
|
/*
|
|
* TupleType type for Edges
|
|
*/
|
|
static const string hlGetHlGraphNodesTupleTypeInfo()
|
|
{
|
|
return "(" + Tuple::BasicType() +
|
|
"(" +
|
|
"(Source " + CcInt::BasicType() + ")" +
|
|
")" +
|
|
")";
|
|
}
|
|
|
|
|
|
/*
|
|
* Definition of Field-Indexes for HlGraph Orel Representation
|
|
*/
|
|
static const int HL_INDEX_OF_SOURCE_IN_HL_GRAPH_NODES = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
* OrderedRelation type for a HlGraph
|
|
* Used for creation of new OrderedRelation Objects, new Tuples of
|
|
* this OrderedRelation or cloning or deleting of an
|
|
* OrderedRelation of this type
|
|
*/
|
|
static const string hlGetHlGraphOrelTypeInfo()
|
|
{
|
|
return "(" + OrderedRelation::BasicType() +
|
|
hlGetHlGraphTupleTypeInfo() +
|
|
"(Source)" +
|
|
")";
|
|
}
|
|
|
|
|
|
/*
|
|
* TupleType type for Edges
|
|
*/
|
|
static const string hlGetHlGraphTupleTypeInfo()
|
|
{
|
|
return "(" + Tuple::BasicType() +
|
|
"(" +
|
|
"(Source " + CcInt::BasicType() + ")" +
|
|
"(Target " + CcInt::BasicType() + ")" +
|
|
"(SourceIndex " + CcInt::BasicType() + ")" +
|
|
"(TargetIndex " + CcInt::BasicType() + ")" +
|
|
"(SourceRank " + CcInt::BasicType() + ")" +
|
|
"(IsForward " + CcInt::BasicType() + ")" +
|
|
"(IsReverse " + CcInt::BasicType() + ")" +
|
|
"(ShortcutParentIdForward " + CcInt::BasicType() + ")" +
|
|
"(ShortcutParentIdReverse " + CcInt::BasicType() + ")" +
|
|
"(ShortcutParentIndexForward " + CcInt::BasicType() + ")" +
|
|
"(ShortcutParentIndexReverse " + CcInt::BasicType() + ")" +
|
|
"(WeightForward " + CcReal::BasicType() + ")" +
|
|
"(WeightReverse " + CcReal::BasicType() + ")" +
|
|
")" +
|
|
")";
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Definition of Field-Indexes for HlGraph Orel Representation
|
|
*/
|
|
static const int HL_INDEX_OF_SOURCE_IN_HL_GRAPH = 0;
|
|
static const int HL_INDEX_OF_TARGET_IN_HL_GRAPH = 1;
|
|
static const int HL_INDEX_OF_SOURCE_INDEX_IN_HL_GRAPH = 2;
|
|
static const int HL_INDEX_OF_TARGET_INDEX_IN_HL_GRAPH = 3;
|
|
static const int HL_INDEX_OF_SOURCE_RANK_IN_HL_GRAPH = 4;
|
|
static const int HL_INDEX_OF_IS_FORWARD_IN_HL_GRAPH = 5;
|
|
static const int HL_INDEX_OF_IS_REVERSE_IN_HL_GRAPH = 6;
|
|
static const int HL_INDEX_OF_PARENT_ID_FORWARD_IN_HL_GRAPH = 7;
|
|
static const int HL_INDEX_OF_PARENT_ID_REVERSE_IN_HL_GRAPH = 8;
|
|
static const int HL_INDEX_OF_PARENT_INDEX_FORWARD_IN_HL_GRAPH = 9;
|
|
static const int HL_INDEX_OF_PARENT_INDEX_REVERSE_IN_HL_GRAPH = 10;
|
|
static const int HL_INDEX_OF_WEIGHT_FORWARD_IN_HL_GRAPH = 11;
|
|
static const int HL_INDEX_OF_WEIGHT_REVERSE_IN_HL_GRAPH = 12;
|
|
|
|
|
|
|
|
/*
|
|
* Gets an OrderedRelation containing Edges from OSM Import
|
|
* and transforms its contents into an internal graph structure.
|
|
* The internal graph is represented as an adjacency list.
|
|
* There all Edges are grouped by their sourceNodeId within HlNodeEntry.
|
|
* An Edge entry only consists of its targetNodeId, the edge weight and
|
|
* two booleans to distinguish between original edges an so called
|
|
* reverse edges which are inverted edges stored additionally to
|
|
* perform backward searches.
|
|
* That for theres also a second edgeWeight for those reverse edges
|
|
* in case an original edge from u to v has got another weight
|
|
* than the original edge from v to u.
|
|
* Instead of storing the edges targetId we store the index position
|
|
* of the target node within the hlGraph.
|
|
* This for we iterate through the given orel twice. First to get
|
|
* all index positions of all nodes, second to create the hlGraph
|
|
* using these index positions.
|
|
*
|
|
* @param nodesOrel the orel to be transformed
|
|
* @param edgesOrel an orel just containing all nodes Ids of the OSM-Graph
|
|
* @param nodesEdgesVector by reference the adjacency-list to fill
|
|
*
|
|
* @return true since all modifications take place in the given parameters
|
|
*/
|
|
bool hlTransformOrelToHlGraph(OrderedRelation* nodesOrel,
|
|
OrderedRelation* edgesOrel,
|
|
std::vector<HlNodeEntry*> &nodesEdgesVector) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlTransformOrelToHlGraph" << endl);
|
|
#endif
|
|
|
|
//default rank to set within hlGraph, should be -1
|
|
int defaultRank = -1;
|
|
std::map<int, int> indexedNodeIds;
|
|
|
|
GenericRelationIterator* nodesListOrelIter = nodesOrel->MakeScan();
|
|
|
|
//Get first Tuple
|
|
Tuple* currNode = nodesListOrelIter->GetNextTuple();
|
|
|
|
int currIndex = 0;
|
|
|
|
//Iterate over all Tuples first time
|
|
// and create index-mapping
|
|
while(currNode)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("next edge from while" << endl);
|
|
#endif
|
|
CcInt* currNodeId = (CcInt*) currNode->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_HL_GRAPH_NODES);
|
|
|
|
indexedNodeIds.insert(std::make_pair(currNodeId->GetIntval(),
|
|
currIndex++));
|
|
|
|
//get next Tuple from Orel
|
|
currNode->DeleteIfAllowed();
|
|
currNode = 0;
|
|
currNode = nodesListOrelIter->GetNextTuple();
|
|
}
|
|
delete nodesListOrelIter;
|
|
|
|
GenericRelationIterator* edgesOrelIter = edgesOrel->MakeScan();
|
|
|
|
//Get first Tuple
|
|
Tuple* currEdge = edgesOrelIter->GetNextTuple();
|
|
|
|
int currOrderedNodeId = -1;
|
|
std::vector<HlEdgeEntry*>* currSourceEdgesVector = 0;
|
|
std::vector<HlEdgeEntry*>* currTargetEdgesVector = 0;
|
|
|
|
//Iterate over all Tuples second time
|
|
// and create hlGraph
|
|
while(currEdge)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("next edge from while" << endl);
|
|
#endif
|
|
|
|
CcInt* currEdgeSource = (CcInt*) currEdge->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
CcInt* currEdgeTarget = (CcInt*) currEdge->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
CcReal* currEdgeWeight = (CcReal*) currEdge->GetAttribute(
|
|
HL_INDEX_OF_COSTS_IN_EDGE_TUPLE);
|
|
|
|
int currSourceNodeId = currEdgeSource->GetIntval();
|
|
int currTargetNodeId = currEdgeTarget->GetIntval();
|
|
|
|
std::map<int, int>::iterator currSourceIndexIter =
|
|
indexedNodeIds.find(currSourceNodeId);
|
|
|
|
if(currSourceIndexIter == indexedNodeIds.end())
|
|
{
|
|
LogError("Fehler, SourceNode (" << currSourceNodeId
|
|
<< ") der aktuellen Kante existiert nicht."
|
|
<< endl);
|
|
|
|
hlFreeHlGraph(nodesEdgesVector);
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
std::map<int, int>::iterator currTargetIndexIter =
|
|
indexedNodeIds.find(currTargetNodeId);
|
|
|
|
if(currTargetIndexIter == indexedNodeIds.end())
|
|
{
|
|
LogError("Fehler, TargetNode (" << currTargetNodeId
|
|
<< ") der aktuellen Kante existiert nicht."
|
|
<< endl);
|
|
|
|
hlFreeHlGraph(nodesEdgesVector);
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
int currSourceIndex = (*currSourceIndexIter).second;
|
|
int currTargetIndex = (*currTargetIndexIter).second;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("check nodeId (" << currSourceNodeId << ") is new (old: "
|
|
<< currOrderedNodeId << ")" << endl);
|
|
#endif
|
|
|
|
|
|
//check whether we reached next sourceId
|
|
if(currOrderedNodeId != currSourceNodeId)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("yes, it is new" << endl);
|
|
#endif
|
|
//set next nodeId and create new nodeEntry
|
|
currOrderedNodeId = currSourceNodeId;
|
|
|
|
//check whether current SourceNode still exists
|
|
// due to reverse-edges
|
|
HlNodeEntry* currHlNodeEntry =
|
|
nodesEdgesVector[currSourceIndex];
|
|
|
|
if(currHlNodeEntry)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("source node Id (" << currSourceNodeId <<
|
|
") still exists" << endl);
|
|
#endif
|
|
|
|
currSourceEdgesVector = currHlNodeEntry->getEdgesVector();
|
|
}else{
|
|
#ifdef USEDEBUG
|
|
LogDebug("source node Id (" << currSourceNodeId <<
|
|
") does not exist" << endl);
|
|
#endif
|
|
|
|
//we need a new one
|
|
currSourceEdgesVector = new std::vector<HlEdgeEntry*>();
|
|
|
|
currHlNodeEntry = new HlNodeEntry();
|
|
currHlNodeEntry->setNodeId(currSourceNodeId);
|
|
currHlNodeEntry->setRankValue(defaultRank);
|
|
currHlNodeEntry->setEdgesVector(currSourceEdgesVector);
|
|
|
|
nodesEdgesVector[currSourceIndex] = currHlNodeEntry;
|
|
}
|
|
}
|
|
|
|
|
|
//get targetEdgesVector for reverse edges
|
|
|
|
//check whether current TargetNode still exists
|
|
// as sourceNode due to reverse-edges or forward-edges
|
|
HlNodeEntry* currTargetHlNodeEntry =
|
|
nodesEdgesVector[currTargetIndex];
|
|
|
|
|
|
//if the targetNodeId still exists
|
|
// we just edit the existing edgeEntry
|
|
if(currTargetHlNodeEntry)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("target node Id (" << currTargetNodeId <<
|
|
") still exists" << endl);
|
|
#endif
|
|
|
|
currTargetEdgesVector = currTargetHlNodeEntry->getEdgesVector();
|
|
}else{
|
|
#ifdef USEDEBUG
|
|
LogDebug("target node Id (" << currTargetNodeId <<
|
|
") does not exist" << endl);
|
|
#endif
|
|
|
|
//we need a new one
|
|
currTargetEdgesVector = new std::vector<HlEdgeEntry*>();
|
|
|
|
currTargetHlNodeEntry = new HlNodeEntry();
|
|
currTargetHlNodeEntry->setNodeId(currTargetNodeId);
|
|
currTargetHlNodeEntry->setRankValue(defaultRank);
|
|
currTargetHlNodeEntry->setEdgesVector(currTargetEdgesVector);
|
|
|
|
nodesEdgesVector[currTargetIndex] = currTargetHlNodeEntry;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("add forward edge (" << currSourceNodeId << ", "
|
|
<< currTargetNodeId << ")" << endl);
|
|
#endif
|
|
//check whether the targetNodeId still exists
|
|
// due to reverseEdges
|
|
HlEdgeEntry* currSourceEdgeEntry =
|
|
hlGetEdgeFromVector(currSourceEdgesVector, currTargetIndex);
|
|
|
|
//create new if does not exist
|
|
if(!currSourceEdgeEntry)
|
|
{
|
|
currSourceEdgeEntry = new HlEdgeEntry();
|
|
|
|
//add current forward edge (u, v)
|
|
currSourceEdgeEntry->setTargetIndex(currTargetIndex);
|
|
currSourceEdgeEntry->setWeightForward(
|
|
currEdgeWeight->GetRealval());
|
|
currSourceEdgeEntry->setIsForward(true);
|
|
currSourceEdgesVector->push_back(currSourceEdgeEntry);
|
|
}else{
|
|
//else just edit fields
|
|
currSourceEdgeEntry->setWeightForward(
|
|
currEdgeWeight->GetRealval());
|
|
currSourceEdgeEntry->setIsForward(true);
|
|
}
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("add reverse edge (" << currTargetNodeId << ", "
|
|
<< currSourceNodeId << ")" << endl);
|
|
#endif
|
|
//check whether the sourceNodeId still exists
|
|
// due to forwardEdges
|
|
HlEdgeEntry* currTargetEdgeEntry =
|
|
hlGetEdgeFromVector(currTargetEdgesVector, currSourceIndex);
|
|
|
|
//create new if does not exist
|
|
if(!currTargetEdgeEntry)
|
|
{
|
|
currTargetEdgeEntry = new HlEdgeEntry();
|
|
|
|
//add the same edge as reverse edge (v, u)
|
|
currTargetEdgeEntry->setTargetIndex(currSourceIndex);
|
|
currTargetEdgeEntry->setWeightReverse(
|
|
currEdgeWeight->GetRealval());
|
|
currTargetEdgeEntry->setIsReverse(true);
|
|
currTargetEdgesVector->push_back(currTargetEdgeEntry);
|
|
}else{
|
|
//else just edit fields
|
|
currTargetEdgeEntry->setWeightReverse(
|
|
currEdgeWeight->GetRealval());
|
|
currTargetEdgeEntry->setIsReverse(true);
|
|
}
|
|
|
|
|
|
//get next Tuple from Orel
|
|
currEdge->DeleteIfAllowed();
|
|
currEdge = 0;
|
|
currEdge = edgesOrelIter->GetNextTuple();
|
|
}
|
|
|
|
delete edgesOrelIter;
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlTransformOrelToHlGraph" << endl);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Iterates through the given vector and compares each element
|
|
* with the given targetNodeId.
|
|
* If they match it returns the pointer to the current HlEdgeEntry-element.
|
|
*
|
|
* @param edgeVector the Vector to be searched in
|
|
* @param targetNodeIndex the index positionof the node to be searched for
|
|
* @return the pointer to the desired object if found, null else
|
|
*/
|
|
HlEdgeEntry* hlGetEdgeFromVector(std::vector<HlEdgeEntry*>* edgeVector,
|
|
int targetNodeIndex) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlGetEdgeFromVector" << endl);
|
|
#endif
|
|
|
|
HlEdgeEntry* resultEdgeEntry = 0;
|
|
for (std::vector<HlEdgeEntry*>::iterator it =
|
|
edgeVector->begin(); it != edgeVector->end(); ++it)
|
|
{
|
|
HlEdgeEntry* currEdgeEntry = *it;
|
|
#ifdef USEDEBUG
|
|
LogDebug("next edge from vector: " <<
|
|
currEdgeEntry->getTargetIndex() << endl);
|
|
#endif
|
|
if(currEdgeEntry->getTargetIndex() == targetNodeIndex)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("match" << endl);
|
|
#endif
|
|
resultEdgeEntry = currEdgeEntry;
|
|
break;
|
|
}
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlGetEdgeFromVector" << endl);
|
|
#endif
|
|
|
|
return resultEdgeEntry;
|
|
}
|
|
|
|
|
|
/*
|
|
* Calculates the priority for the given sourceNodeId.
|
|
* Does ignor edges not existing within priority multimap
|
|
* since these nodes still have been contracted.
|
|
*
|
|
* @param currNodeEntry the current nodeEntry to calculate its priority
|
|
* @param nodesEdgesVector by reference the whole adjacency-list
|
|
* @param initPriorityQueue indicated whethere the rankedMultimap is
|
|
* being built up right now
|
|
* @param currCalcFunction defines which rank-calculation function
|
|
* shall be used
|
|
* @param currTmpCounter only used for sequential rank calculation
|
|
* @return the calculated rank
|
|
*/
|
|
double hlCalcPriorityOfHlNodeEntry(HlNodeEntry* currNodeEntry,
|
|
std::vector<HlNodeEntry*> &nodesEdgesVector, bool initPriorityQueue,
|
|
int currCalcFunction, int currTmpCounter) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlCalcPriorityOfHlNodeEntry" << endl);
|
|
#endif
|
|
|
|
if(currCalcFunction == 0){
|
|
//EdgeDifference, processed afterwards
|
|
}else if(currCalcFunction == 1){
|
|
//return low enough number such that the recalculated rank
|
|
// is still the nex ont
|
|
if(!initPriorityQueue)
|
|
{
|
|
return -10;
|
|
}
|
|
//Random, return directly
|
|
time_t t;
|
|
|
|
time(&t);
|
|
srand((unsigned int)t); /* Zufallsgenerator initialisieren*/
|
|
|
|
return rand();
|
|
}else if(currCalcFunction == 2){
|
|
//return low enough number such that the recalculated rank
|
|
// is still the nex ont
|
|
if(!initPriorityQueue)
|
|
{
|
|
return -10;
|
|
}
|
|
//sequence, return next
|
|
return currTmpCounter;
|
|
}
|
|
|
|
double calculatedPriority = 0;
|
|
|
|
int inOutEdgesCount = 0;
|
|
int inEdgesCount = 0;
|
|
int outEdgesCount = 0;
|
|
|
|
std::vector<HlEdgeEntry*>* edgeVector = currNodeEntry->getEdgesVector();
|
|
|
|
for (std::vector<HlEdgeEntry*>::iterator it =
|
|
edgeVector->begin(); it != edgeVector->end(); ++it)
|
|
{
|
|
HlEdgeEntry* currEdgeEntry = *it;
|
|
|
|
int currTargetIndex = currEdgeEntry->getTargetIndex();
|
|
HlNodeEntry* currTargetNodeEntry =
|
|
nodesEdgesVector[currTargetIndex];
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("next edge from vector: (" <<
|
|
currNodeEntry->getNodeId() << ", " <<
|
|
currTargetNodeEntry->getNodeId() << ")" << endl);
|
|
#endif
|
|
|
|
|
|
//check whether target node still has been contracted
|
|
//skip if yes, proceed else
|
|
//still contracted nodes do have a rank > -1
|
|
//also proceed if given flag initPriorityQueue = true
|
|
// which means that the priority multimap is just being built up
|
|
// right now and we will consider all nodes
|
|
int currTargetRank = -1;
|
|
if(!initPriorityQueue)
|
|
{
|
|
currTargetRank = currTargetNodeEntry->getRankValue();
|
|
}
|
|
|
|
|
|
if(currTargetRank == -1)
|
|
{
|
|
//node not contracted yet, proceed
|
|
|
|
if(currEdgeEntry->getIsReverse() &&
|
|
currEdgeEntry->getIsForward())
|
|
{
|
|
//incoming and outgoing edge
|
|
inOutEdgesCount++;
|
|
|
|
}
|
|
else if(currEdgeEntry->getIsReverse())
|
|
{
|
|
//incoming edge oneway
|
|
inEdgesCount++;
|
|
}
|
|
else if (currEdgeEntry->getIsForward())
|
|
{
|
|
//outgoing edge oneway
|
|
outEdgesCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//do calcutation
|
|
|
|
//calculate edge dffierence
|
|
|
|
//total number of incoming and outgoing edges
|
|
int totalInOutEdges = inOutEdgesCount * 2
|
|
+ inEdgesCount + outEdgesCount;
|
|
|
|
//total number of shortcuts to be created
|
|
//do not count nodes being source and target at the same time
|
|
//e.g. if theres an incoming edge from u to v and also there
|
|
// is an edge from v to u we do not count an shortcut from u to u
|
|
// which would be nonsense
|
|
//Thats why we subtract inOutEdgesCount.
|
|
int totalShortcutsToCreate =
|
|
(inOutEdgesCount + inEdgesCount) * (inOutEdgesCount + outEdgesCount)
|
|
- inOutEdgesCount;
|
|
|
|
int edgeDifference = totalShortcutsToCreate - totalInOutEdges;
|
|
#ifdef USEDEBUG
|
|
LogDebug("ED: " << edgeDifference << " = shortcuts: " <<
|
|
totalShortcutsToCreate << " - inoutEdges: " << totalInOutEdges
|
|
<< endl);
|
|
#endif
|
|
|
|
|
|
//multiply by -1 such that we get a min-priority queue
|
|
calculatedPriority = (double) edgeDifference;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlCalcPriorityOfHlNodeEntry" << endl);
|
|
#endif
|
|
|
|
return calculatedPriority;
|
|
}
|
|
|
|
|
|
/*
|
|
* type definitions and
|
|
* comparable function for using priority_queue
|
|
* within nodeContraction
|
|
* Format is: edgeWeightToSource, targetNodeIndex
|
|
*/
|
|
typedef std::pair<double, int> QueuePairType;
|
|
|
|
struct CompareQueueEntry :
|
|
public std::binary_function<QueuePairType, QueuePairType, bool>
|
|
{
|
|
bool operator()
|
|
(const QueuePairType firstQueuePair,
|
|
const QueuePairType secondQueuePair) const
|
|
{
|
|
return firstQueuePair.first > secondQueuePair.first;
|
|
}
|
|
};
|
|
|
|
typedef std::priority_queue<QueuePairType, vector<QueuePairType>,
|
|
CompareQueueEntry> PriorityQueueType;
|
|
|
|
|
|
/*
|
|
* type definitions and comparable function
|
|
* for using priority_queue
|
|
* within hHopForwardSearch
|
|
* Format is: edgeWeightToSource, targetNodeIndex, targetHHop
|
|
*/
|
|
typedef std::pair<double, std::pair<int, int>> QueuePairTypeForwardSearch;
|
|
|
|
struct CompareQueueEntryForwardSearch :
|
|
public std::binary_function<QueuePairTypeForwardSearch,
|
|
QueuePairTypeForwardSearch, bool>
|
|
{
|
|
bool operator()
|
|
(const QueuePairTypeForwardSearch firstQueuePair,
|
|
const QueuePairTypeForwardSearch secondQueuePair) const
|
|
{
|
|
return firstQueuePair.first > secondQueuePair.first;
|
|
}
|
|
};
|
|
|
|
typedef std::priority_queue<QueuePairTypeForwardSearch,
|
|
vector<QueuePairTypeForwardSearch>,
|
|
CompareQueueEntryForwardSearch> PriorityQueueTypeForwardSearch;
|
|
|
|
|
|
/*
|
|
* Iterates through the given graph and creates a priority for every node.
|
|
* Inserts these priorities into the given multimap.
|
|
*
|
|
* @param nodesEdgesVector by reference the adjacency-list to fill
|
|
* @param priorityQueue by reference priorityQueue to fill
|
|
* @param currCalcFunction the rank-calcfuntion to be used
|
|
* @return true since all modifications are done within the given parameters
|
|
*/
|
|
bool hlInitPriorityQueueOfHlGraph(
|
|
std::vector<HlNodeEntry*> &nodesEdgesVector,
|
|
PriorityQueueType &priorityQueue, int currCalcFunction) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlInitPriorityQueueOfHlGraph" << endl);
|
|
#endif
|
|
|
|
//iterate over all nodes and initial calc their priority
|
|
#ifdef USEDEBUG
|
|
LogDebug("init priority" << endl);
|
|
#endif
|
|
|
|
//used for sequential rank calculation if used
|
|
int tmpCalcCounter = 0;
|
|
|
|
for (uint i = 0; i < nodesEdgesVector.size(); i++)
|
|
{
|
|
HlNodeEntry* currNodeEntry = nodesEdgesVector[i];
|
|
|
|
//calc priority of current node
|
|
double currPriority = 0.0;
|
|
bool initPriorityQueue = true;
|
|
currPriority = hlCalcPriorityOfHlNodeEntry(currNodeEntry,
|
|
nodesEdgesVector, initPriorityQueue, currCalcFunction,
|
|
tmpCalcCounter++);
|
|
|
|
//store priority in queue
|
|
priorityQueue.push(std::make_pair(currPriority, i));
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlInitPriorityQueueOfHlGraph" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Iteratively does Contraction for every element within the given queue.
|
|
* Recalculates the priority of every node chosen next from queue
|
|
* for better contaction.
|
|
* Stores a sequenced rank for every node in order of its contraction.
|
|
*
|
|
* @param nodesEdgesVector by reference the adjacency-list
|
|
* @param priorityQueue by reference the priorityQueue to work off
|
|
* @param hHopSize the size how depth hHop searches shall be processed
|
|
* @param skipContractionRemainingCount the size after how many remaining
|
|
* elements from contraction recalculation of priority shall be
|
|
* stopped and elements are just contracted in the order so far
|
|
* @param currCalcFunction defines which rank-calculation function shall
|
|
* shall be used
|
|
* @return true since all modifications are done within the given parameters
|
|
*/
|
|
bool hlDoContractionOfHlGraph(std::vector<HlNodeEntry*> &nodesEdgesVector,
|
|
PriorityQueueType &priorityQueue,
|
|
int hHopSize, int skipContractionRemainingCount,
|
|
int currCalcFunction) const
|
|
{
|
|
#ifdef USEINFO
|
|
LogInfo("start hlDoContractionOfHlGraph" << endl);
|
|
#endif
|
|
|
|
int newRankSequence = 0;
|
|
size_t skipRecalcRank = (size_t) skipContractionRemainingCount;
|
|
|
|
int progressCount = 0;
|
|
#ifdef USEPERF
|
|
bool perfBool = false;
|
|
|
|
double perfTime = 0.0;
|
|
double perfTime2 = 0.0;
|
|
double perfTime3 = 0.0;
|
|
double perfTime4 = 0.0;
|
|
#endif
|
|
|
|
//iterate while queue is not empty
|
|
while(!priorityQueue.empty())
|
|
{
|
|
progressCount++;
|
|
#ifdef USEPERF
|
|
|
|
if(progressCount % getProgressInterval() == 0)
|
|
{
|
|
perfBool = true;
|
|
}
|
|
|
|
if(perfBool)
|
|
{
|
|
perfTime = getCurrentTimeInMs();
|
|
}
|
|
#endif
|
|
|
|
//get first element of map
|
|
QueuePairType currQueuePair = priorityQueue.top();
|
|
int currPriorityContraction = currQueuePair.first;
|
|
int currNodeIndex = currQueuePair.second;
|
|
HlNodeEntry* currNodeEntry = nodesEdgesVector[currNodeIndex];
|
|
|
|
//remove node from map its not used any more
|
|
//but we may reinsert it when priority has changed
|
|
priorityQueue.pop();
|
|
|
|
|
|
#ifdef USEINFO
|
|
if(progressCount % getProgressInterval() == 0)
|
|
{
|
|
int currNodeIdContraction = currNodeEntry->getNodeId();
|
|
LogInfo("next top element is: nodeId: " << currNodeIdContraction
|
|
<< " priority: " << currPriorityContraction
|
|
<< " elements left:" << priorityQueue.size() - 1 << endl);
|
|
}
|
|
#endif
|
|
|
|
//recalculate the priority of the first element
|
|
//Only recalculate if we are not processing the last X Nodes
|
|
// where x depends on the soze of the network an is
|
|
// n = 10.000
|
|
//there probably is no lower rank than -2
|
|
// (in case a death end node is contracted)
|
|
double recalculatedPriority = -10.0;
|
|
|
|
if(priorityQueue.size() >= skipRecalcRank)
|
|
{
|
|
bool initPriorityQueue = false;
|
|
recalculatedPriority = hlCalcPriorityOfHlNodeEntry(
|
|
currNodeEntry, nodesEdgesVector, initPriorityQueue,
|
|
currCalcFunction, -1
|
|
);
|
|
}
|
|
|
|
|
|
//check whether the priority has increased
|
|
if(recalculatedPriority > currPriorityContraction)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("reinserting, priority has increased from "
|
|
<< currPriorityContraction
|
|
<< " to: " << recalculatedPriority << endl);
|
|
#endif
|
|
//if yes we need to reinsert this element with its
|
|
// recalculated priority
|
|
//and repeat getting the new top element
|
|
priorityQueue.push(
|
|
std::make_pair(recalculatedPriority, currNodeIndex));
|
|
continue;
|
|
}
|
|
|
|
|
|
//store rank in hlGraph for later use
|
|
//for uniqueness we use a novel increasing sequence for that
|
|
currNodeEntry->setRankValue(newRankSequence++);
|
|
|
|
|
|
|
|
|
|
#ifdef USEPERF
|
|
if(perfBool)
|
|
{
|
|
perfTime2 = getCurrentTimeInMs();
|
|
}
|
|
#endif
|
|
|
|
|
|
//contract
|
|
hlContractNodeOfHlGraph(nodesEdgesVector, currNodeEntry,
|
|
currNodeIndex, hHopSize);
|
|
|
|
|
|
#ifdef USEPERF
|
|
if(perfBool)
|
|
{
|
|
perfTime3 = getCurrentTimeInMs();
|
|
LogPerf("perf: duration of contraction itself in: (ms) "
|
|
<< fixed << (perfTime3 - perfTime2) << endl);
|
|
}
|
|
#endif
|
|
|
|
if(priorityQueue.size() <= skipRecalcRank)
|
|
{
|
|
//recalculate priorities of neighbours of contracted node
|
|
hlRecalculateNeighboursInHlGraph(nodesEdgesVector,
|
|
currNodeEntry);
|
|
}
|
|
|
|
|
|
#ifdef USEPERF
|
|
if(perfBool)
|
|
{
|
|
perfTime4 = getCurrentTimeInMs();
|
|
|
|
LogPerf(
|
|
"perf: duration of receiving and contracting a node: (ms) "
|
|
<< fixed << (perfTime4 - perfTime) << endl);
|
|
|
|
perfTime = 0.0;
|
|
perfTime2 = 0.0;
|
|
perfTime3 = 0.0;
|
|
perfTime4 = 0.0;
|
|
|
|
perfBool = false;
|
|
}
|
|
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("finish hlDoContractionOfHlGraph" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Contracts a specific node.
|
|
* Contraction mean that shortcuts will be created
|
|
* and added to the existing graph structure.
|
|
* For every incoming node u and every outgoing node w there will
|
|
* be a shortcut created with the given nodeIdV as parent.
|
|
* Nodes or edges are not deleted here because still contracted edges
|
|
* and nodes are identified by not finding them within the ranks-queue.
|
|
* Does ignor edges not existing within ranked multimap
|
|
* since these nodes still have been contracted.
|
|
*
|
|
* @param nodesEdgesVector by reference the adjacency-list
|
|
* @param currNodeEntryV the current node v to be contracted.
|
|
* @param nodeIndexV the index position of node v within hlGraph.
|
|
* @param hHopSize the size how depth hHop searches shall be processed
|
|
* @return true since all modifications are done within the given parameters
|
|
*/
|
|
bool hlContractNodeOfHlGraph(std::vector<HlNodeEntry*> &nodesEdgesVector,
|
|
HlNodeEntry* currNodeEntryV, int nodeIndexV, int hHopSize) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlContractNodeOfHlGraph" << endl);
|
|
#endif
|
|
|
|
|
|
//get EdgesTuple of curent node to be contracted
|
|
std::vector<HlEdgeEntry*>* currEdgesV =
|
|
currNodeEntryV->getEdgesVector();
|
|
|
|
//save all incoming edges for later h-hop forward search
|
|
std::vector<HlEdgeEntry*> incomingEdgesUV;
|
|
|
|
//store results of one hop reverse search
|
|
std::map<int, std::vector<std::pair<int, double>>>
|
|
reverseSearchResultsXW;
|
|
std::map<int, double> distancesVW;
|
|
|
|
//iterate over all incoming and outgoing edges
|
|
for (std::vector<HlEdgeEntry*>::iterator currEdgesVIter =
|
|
currEdgesV->begin() ; currEdgesVIter != currEdgesV->end();
|
|
++currEdgesVIter)
|
|
{
|
|
HlEdgeEntry* currEdgeEntryV = *currEdgesVIter;
|
|
|
|
//check whether edge is a reverse/incoming edge (u, v)
|
|
// remember it then for later forward search
|
|
// do one-hop reverse search if its a forward/outgoing edge
|
|
if(currEdgeEntryV->getIsReverse())
|
|
{
|
|
incomingEdgesUV.push_back(currEdgeEntryV);
|
|
}
|
|
|
|
if(currEdgeEntryV->getIsForward())
|
|
{
|
|
|
|
//get edgeVector of w
|
|
int nodeIndexW = currEdgeEntryV->getTargetIndex();
|
|
HlNodeEntry* currNodeEntryW = nodesEdgesVector[nodeIndexW];
|
|
|
|
int rankW = currNodeEntryW->getRankValue();
|
|
std::vector<HlEdgeEntry*>* edgesVectorW =
|
|
currNodeEntryW->getEdgesVector();
|
|
|
|
|
|
//skip if targetNode w still has been contracted
|
|
// they are stil contracted if they do have a rank != -1
|
|
if(rankW != -1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
//insert for lookups while hHop Forward search
|
|
distancesVW.insert(std::make_pair(
|
|
currEdgeEntryV->getTargetIndex(),
|
|
currEdgeEntryV->getWeightForward()
|
|
));
|
|
|
|
#ifdef USEDEBUG
|
|
int nodeIdW = currNodeEntryW->getNodeId();
|
|
LogDebug("next node w: " << nodeIdW << " with index: "
|
|
<< nodeIndexW << " with rank: " << rankW << endl);
|
|
#endif
|
|
|
|
|
|
// store the additional information that this is
|
|
// an upward-edge (for easier deletion later on
|
|
// creating Up- and Downwardgraphs
|
|
currEdgeEntryV->setIsUpwardOriginal(true);
|
|
|
|
|
|
//iterate over all incoming edges (x, w) to store them as
|
|
// one hop reverse search
|
|
for (std::vector<HlEdgeEntry*>::iterator
|
|
edgesVectorWIter = edgesVectorW->begin();
|
|
edgesVectorWIter != edgesVectorW->end();
|
|
++edgesVectorWIter)
|
|
{
|
|
HlEdgeEntry* currEdgeEntryXW = *edgesVectorWIter;
|
|
|
|
int nodeIndexX = currEdgeEntryXW->getTargetIndex();
|
|
HlNodeEntry* currNodeEntryX = nodesEdgesVector[nodeIndexX];
|
|
|
|
//skip if is v itself, we still stored its distance
|
|
// also skip if is no incoming edge to t
|
|
// skip still contracted nodes
|
|
if(!currEdgeEntryXW->getIsReverse()
|
|
|| nodeIndexX == nodeIndexV
|
|
|| currNodeEntryX->getRankValue() != -1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//store x with distance to current w
|
|
double currDistXW = currEdgeEntryXW->getWeightReverse();
|
|
|
|
//creates a new entry if nodeIndexX it did not exist
|
|
reverseSearchResultsXW[nodeIndexX].push_back(
|
|
std::make_pair(nodeIndexW, currDistXW));
|
|
|
|
}
|
|
} //finish reverse search of current node
|
|
}//finish iteration over all adjacent nodes
|
|
|
|
|
|
//iterate over all remembered incoming nodes
|
|
//iterate over all incoming edges (= reverse edges) (u, v)
|
|
for (std::vector<HlEdgeEntry*>::iterator
|
|
incomingEdgesUVIter = incomingEdgesUV.begin();
|
|
incomingEdgesUVIter != incomingEdgesUV.end();
|
|
++incomingEdgesUVIter)
|
|
{
|
|
HlEdgeEntry* currEdgeEntryIncomingUV = *incomingEdgesUVIter;
|
|
|
|
int nodeIndexU = currEdgeEntryIncomingUV->getTargetIndex();
|
|
|
|
|
|
//get edgeVector of u
|
|
HlNodeEntry* currNodeEntryU = nodesEdgesVector[nodeIndexU];
|
|
int rankU = currNodeEntryU->getRankValue();
|
|
std::vector<HlEdgeEntry*>* edgesVectorU =
|
|
currNodeEntryU->getEdgesVector();
|
|
|
|
|
|
//skip if sourceNode u still has been contracted
|
|
// they are stil contracted if they do have a rank != -1
|
|
if(rankU != -1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
// store the additional information that this is
|
|
// an reverse-upward-edge (for easier deletion later on
|
|
// creating Up- and Downwardgraphs
|
|
// we just check if this edge not yet still has been flagged
|
|
// with this information
|
|
// such that we only set this flag here if the current edge
|
|
// actually is an oneway on the graph
|
|
if(!currEdgeEntryIncomingUV->getIsUpwardOriginal())
|
|
{
|
|
currEdgeEntryIncomingUV->setIsUpwardOriginal(true);
|
|
}
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
int nodeIdU = currNodeEntryU->getNodeId();
|
|
LogDebug("next node u: " << nodeIdU << " with rank: "
|
|
<< rankU << endl);
|
|
#endif
|
|
|
|
//copy distancesVW for make shortcut creation easier
|
|
std::map<int, double> distancesVWCopy = distancesVW;
|
|
|
|
|
|
//directly erase current w == u from distancesVWCopy
|
|
std::map<int, double>::iterator distCopyCurrUIter =
|
|
distancesVWCopy.find(nodeIndexU);
|
|
|
|
if(distCopyCurrUIter != distancesVWCopy.end())
|
|
{
|
|
distancesVWCopy.erase(distCopyCurrUIter);
|
|
}
|
|
|
|
|
|
double currDistUV = currEdgeEntryIncomingUV->getWeightReverse();
|
|
|
|
//do h-Hop forward search
|
|
hlDoHHopForwardSearchInHlGraph(nodesEdgesVector,
|
|
reverseSearchResultsXW, distancesVWCopy, edgesVectorU,
|
|
nodeIndexU, nodeIndexV, currDistUV, hHopSize);
|
|
|
|
|
|
//iterate over all remaining elements from distancesVWCopy
|
|
//create shortcut for every pair with current sourceNode
|
|
for (std::map<int, double>::iterator
|
|
distancesVWCopyIter = distancesVWCopy.begin();
|
|
distancesVWCopyIter != distancesVWCopy.end();
|
|
++distancesVWCopyIter)
|
|
{
|
|
int nodeIndexWShortcut = (*distancesVWCopyIter).first;
|
|
double currDistVWShortcut = (*distancesVWCopyIter).second;
|
|
|
|
//skip if u == w
|
|
if(nodeIndexU == nodeIndexWShortcut)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
HlNodeEntry* currNodeEntryWShortcut =
|
|
nodesEdgesVector[nodeIndexWShortcut];
|
|
std::vector<HlEdgeEntry*>* edgesVectorWShortcut =
|
|
currNodeEntryWShortcut->getEdgesVector();
|
|
|
|
double currShortcutWeight = currDistUV + currDistVWShortcut;
|
|
|
|
//check whether an edge (u, w) still exists
|
|
// for creating a forward edge
|
|
HlEdgeEntry* currShortcutUW =
|
|
hlGetEdgeFromVector(edgesVectorU, nodeIndexWShortcut);
|
|
|
|
//check whether an edge (w, u) still exists
|
|
// for creating a reverse edge
|
|
HlEdgeEntry* currShortcutWU =
|
|
hlGetEdgeFromVector(edgesVectorWShortcut, nodeIndexU);
|
|
|
|
|
|
//merge UW if edge still exists, create new else
|
|
if(currShortcutUW)
|
|
{
|
|
#ifdef USEDEBUG
|
|
int nodeIdU = currNodeEntryU->getNodeId();
|
|
int nodeIdW = currNodeEntryWShortcut->getNodeId();
|
|
LogDebug("edge (u, w) (" << nodeIdU << ", " << nodeIdW <<
|
|
") still exists going to merge" << endl);
|
|
#endif
|
|
|
|
currShortcutUW->setIsForward(true);
|
|
currShortcutUW->setParentIndexForward(nodeIndexV);
|
|
currShortcutUW->setWeightForward(currShortcutWeight);
|
|
}else
|
|
{
|
|
#ifdef USEDEBUG
|
|
int nodeIdU = currNodeEntryU->getNodeId();
|
|
HlNodeEntry* currNodeEntryWShortcut =
|
|
nodesEdgesVector[nodeIndexWShortcut];
|
|
int nodeIdW = currNodeEntryWShortcut->getNodeId();
|
|
LogDebug("edge (u, w) (" << nodeIdU << ", " << nodeIdW <<
|
|
") does not exist, create new" << endl);
|
|
#endif
|
|
|
|
//create new and append to edgesVector
|
|
currShortcutUW = new HlEdgeEntry();
|
|
currShortcutUW->setIsForward(true);
|
|
currShortcutUW->setParentIndexForward(nodeIndexV);
|
|
currShortcutUW->setTargetIndex(nodeIndexWShortcut);
|
|
currShortcutUW->setWeightForward(currShortcutWeight);
|
|
|
|
edgesVectorU->push_back(currShortcutUW);
|
|
}
|
|
|
|
//merge WU if existed crete new else
|
|
if(currShortcutWU)
|
|
{
|
|
#ifdef USEDEBUG
|
|
int nodeIdU = currNodeEntryU->getNodeId();
|
|
int nodeIdW = currNodeEntryWShortcut->getNodeId();
|
|
LogDebug("edge (w, u) (" << nodeIdW << ", " << nodeIdU <<
|
|
") still exists going to merge" << endl);
|
|
#endif
|
|
|
|
currShortcutWU->setIsReverse(true);
|
|
currShortcutWU->setParentIndexReverse(nodeIndexV);
|
|
currShortcutWU->setWeightReverse(currShortcutWeight);
|
|
}else
|
|
{
|
|
#ifdef USEDEBUG
|
|
int nodeIdU = currNodeEntryU->getNodeId();
|
|
int nodeIdW = currNodeEntryWShortcut->getNodeId();
|
|
LogDebug("edge (w, u) (" << nodeIdW << ", " << nodeIdU <<
|
|
") does not exist, create new" << endl);
|
|
#endif
|
|
|
|
//create new and append to edgesVector
|
|
currShortcutWU = new HlEdgeEntry();
|
|
currShortcutWU->setIsReverse(true);
|
|
currShortcutWU->setParentIndexReverse(nodeIndexV);
|
|
currShortcutWU->setTargetIndex(nodeIndexU);
|
|
currShortcutWU->setWeightReverse(currShortcutWeight);
|
|
|
|
edgesVectorWShortcut->push_back(currShortcutWU);
|
|
}
|
|
}
|
|
|
|
|
|
} // finish iterating over all incoming nodes
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlContractNodeOfHlGraph" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Do H-Hop forward search
|
|
*
|
|
* @param nodesEdgesVector by reference the adjacency-list
|
|
* @param reverseSearchResultsXW by reference the result of reverse search.
|
|
* @param distancesVWCopy by reference the targetNodes with distance to v.
|
|
* @param edgesVectorU the edgesVector of current u.
|
|
* @param nodeIndexU the id of current u.
|
|
* @param nodeIndexV the id of current v to be contracted.
|
|
* @param distUV the distance of current u to v.
|
|
* @param givenHHop the max hop-size.
|
|
* @return true since all modifications are done within the given parameters
|
|
*/
|
|
bool hlDoHHopForwardSearchInHlGraph(
|
|
std::vector<HlNodeEntry*> &nodesEdgesVector,
|
|
std::map<int, std::vector<std::pair<int, double>>> reverseSearchResultsXW,
|
|
std::map<int, double> &distancesVWCopy,
|
|
std::vector<HlEdgeEntry*>* edgesVectorU, int nodeIndexU, int nodeIndexV,
|
|
double distUV, int givenHHop) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlDoHHopForwardSearchInHlGraph" << endl);
|
|
#endif
|
|
|
|
|
|
double distUX = 0.0;
|
|
|
|
//at first check whether curr u is one element of X
|
|
std::map<int, std::vector<std::pair<int, double>>>::iterator
|
|
reverseSearchResultsIter = reverseSearchResultsXW.find(nodeIndexU);
|
|
|
|
|
|
|
|
if(reverseSearchResultsIter != reverseSearchResultsXW.end())
|
|
{
|
|
std::vector<std::pair<int, double>> currVectorXW =
|
|
(*reverseSearchResultsIter).second;
|
|
|
|
//X found check for witness and may remove potential shortcuts
|
|
hlCheckForWitnessInHlGraph(currVectorXW, distancesVWCopy,
|
|
distUX, distUV, nodeIndexU);
|
|
}
|
|
|
|
|
|
//only proceed if givenHHop was chosen correctly
|
|
if(givenHHop < 1)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
//do forward search until givenHHop is reached
|
|
//init queue
|
|
PriorityQueueTypeForwardSearch forwardQueue;
|
|
std::set<int> stillVisitedNodes;
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("initiate hHop forward search" << endl);
|
|
#endif
|
|
|
|
|
|
int currHHop = 1;
|
|
stillVisitedNodes.insert(nodeIndexU);
|
|
|
|
|
|
//skip if there are no more witnesses to find
|
|
if(!distancesVWCopy.empty())
|
|
{
|
|
//iterate over all k of current u
|
|
//to initiate hHop forward search
|
|
for (std::vector<HlEdgeEntry*>::iterator
|
|
edgesVectorUIter = edgesVectorU->begin();
|
|
edgesVectorUIter != edgesVectorU->end();
|
|
++edgesVectorUIter)
|
|
{
|
|
//get data
|
|
HlEdgeEntry* currEdgeEntryUK = *edgesVectorUIter;
|
|
int targetIndexK = currEdgeEntryUK->getTargetIndex();
|
|
|
|
HlNodeEntry* currNodeEntryK = nodesEdgesVector[targetIndexK];
|
|
|
|
//skip if is no forward edge or if k = v
|
|
// or if target is still contracted
|
|
// or if is still visited
|
|
if(!currEdgeEntryUK->getIsForward()
|
|
|| targetIndexK == nodeIndexV
|
|
|| currNodeEntryK->getRankValue() != -1
|
|
|| stillVisitedNodes.find(targetIndexK)
|
|
!= stillVisitedNodes.end()
|
|
)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
forwardQueue.push(std::make_pair(
|
|
currEdgeEntryUK->getWeightForward(),
|
|
std::make_pair(targetIndexK, currHHop)
|
|
));
|
|
}
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("do hHop forward search" << endl);
|
|
#endif
|
|
|
|
|
|
while(!forwardQueue.empty())
|
|
{
|
|
QueuePairTypeForwardSearch currQueuePair = forwardQueue.top();
|
|
forwardQueue.pop();
|
|
|
|
double currDistToSourceUK = currQueuePair.first;
|
|
std::pair<int, int> currTupleQueue = currQueuePair.second;
|
|
|
|
int currNodeIndexK = currTupleQueue.first;
|
|
int currHHopK = currTupleQueue.second;
|
|
|
|
|
|
stillVisitedNodes.insert(currNodeIndexK);
|
|
|
|
HlNodeEntry* currNodeEntryK = nodesEdgesVector[currNodeIndexK];
|
|
|
|
#ifdef USEDEBUG
|
|
int currNodeIdK = currNodeEntryK->getNodeId();
|
|
LogDebug("next node from queue: " << currNodeIdK
|
|
<< " with index: " << currNodeIndexK
|
|
<< " with hHop: " << currHHopK << endl);
|
|
#endif
|
|
|
|
//check for match with an x
|
|
//reuse iterator
|
|
reverseSearchResultsIter =
|
|
reverseSearchResultsXW.find(currNodeIndexK);
|
|
|
|
if(reverseSearchResultsIter != reverseSearchResultsXW.end())
|
|
{
|
|
std::vector<std::pair<int, double>> currVectorXW =
|
|
(*reverseSearchResultsIter).second;
|
|
|
|
|
|
//X found check for witness and may remove potential shortcuts
|
|
hlCheckForWitnessInHlGraph(currVectorXW, distancesVWCopy,
|
|
currDistToSourceUK, distUV, nodeIndexU);
|
|
|
|
//if there are no more nodes w to find a witness path for
|
|
//we can abort the search
|
|
if(distancesVWCopy.empty())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//only proceed if we did not exceed givenHHop
|
|
if(currHHopK >= givenHHop)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("scan new vertices" << endl);
|
|
#endif
|
|
|
|
//get edgeVector of current k
|
|
std::vector<HlEdgeEntry*>* edgesVectorK =
|
|
currNodeEntryK->getEdgesVector();
|
|
|
|
//iterate over all j of current k with edge (k, j)
|
|
for (std::vector<HlEdgeEntry*>::iterator
|
|
edgesVectorKIter = edgesVectorK->begin();
|
|
edgesVectorKIter != edgesVectorK->end();
|
|
++edgesVectorKIter)
|
|
{
|
|
//get data
|
|
HlEdgeEntry* currEdgeEntryKJ = *edgesVectorKIter;
|
|
int currTargetIndexJ = currEdgeEntryKJ->getTargetIndex();
|
|
|
|
HlNodeEntry* currNodeEntryJ =
|
|
nodesEdgesVector[currTargetIndexJ];
|
|
|
|
//skip if is not forward edge or if k = v
|
|
// or if target is still contracted
|
|
if(!currEdgeEntryKJ->getIsForward()
|
|
|| currTargetIndexJ == nodeIndexV
|
|
|| currNodeEntryJ->getRankValue() != -1
|
|
|| stillVisitedNodes.find(currTargetIndexJ)
|
|
!= stillVisitedNodes.end()
|
|
)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//may inserts target nodes which still have been visited
|
|
forwardQueue.push(std::make_pair(
|
|
currEdgeEntryKJ->getWeightForward() + currDistToSourceUK,
|
|
std::make_pair(currTargetIndexJ,
|
|
currHHopK + 1)
|
|
));
|
|
}
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlDoHHopForwardSearchInHlGraph" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Check for Witness during H-Hop forward search
|
|
* and delete w from distancesVWCopy if witness has been found.
|
|
*
|
|
* @param currVectorXW by reference the current x-Array
|
|
* @param distancesVWCopy by reference the targetNodes with distance to v.
|
|
* @param distUX the current distance from u to x
|
|
* @param distUV the current distance from u to v
|
|
* @param currNodeIndexU the index of current node u
|
|
* @return true since all modifications are done within the given parameters
|
|
*/
|
|
bool hlCheckForWitnessInHlGraph(
|
|
std::vector<std::pair<int, double>> &currVectorXW,
|
|
std::map<int, double> &distancesVWCopy,
|
|
double distUX, double distUV, int currNodeIndexU) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlCheckForWitnessInHlGraph" << endl);
|
|
#endif
|
|
|
|
//iterate over all w of current x
|
|
for (std::vector<std::pair<int, double>>::iterator
|
|
currVectorXWIter = currVectorXW.begin();
|
|
currVectorXWIter != currVectorXW.end();
|
|
++currVectorXWIter)
|
|
{
|
|
//get data
|
|
int currNodeIndexW = (*currVectorXWIter).first;
|
|
double currDistXW = (*currVectorXWIter).second;
|
|
|
|
//skip if u == w
|
|
if(currNodeIndexU == currNodeIndexW)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//calc potential shortcut length
|
|
std::map<int, double>::iterator distVWIter =
|
|
distancesVWCopy.find(currNodeIndexW);
|
|
if(distVWIter == distancesVWCopy.end())
|
|
{
|
|
//skip if current w still as been erased
|
|
// from current on hop reverse search
|
|
continue;
|
|
}
|
|
|
|
double currDistVW = (*distVWIter).second;
|
|
double potentialShortcutLength = distUV + currDistVW;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("check for witness for targetIndex: " << currNodeIndexW
|
|
<< " with shortcutLength: " << potentialShortcutLength
|
|
<< " and witness length: " << distUX + currDistXW << endl);
|
|
#endif
|
|
|
|
//check whether witness can be found
|
|
if(potentialShortcutLength >= distUX + currDistXW)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("witness found, erase index: "
|
|
<< currNodeIndexW << endl);
|
|
#endif
|
|
|
|
//witness found, remove potential shortcut
|
|
distancesVWCopy.erase(distVWIter);
|
|
}
|
|
|
|
//break if there are no more witnesses to find
|
|
if(distancesVWCopy.empty())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlCheckForWitnessInHlGraph" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Iterates through all incoming and outgoing neighbours
|
|
* of the current contracted node and recalculates their ranks.
|
|
* Does ignor edges not existing within ranked multimap
|
|
* since these nodes still have been contracted.
|
|
* TODO: not implemented yet.
|
|
* TODO: parameterize the secondo operator with flags to enable or
|
|
* disable this functionality to choose between better
|
|
* contraction and faster processing
|
|
* TODO: ignor still visited nodes and edges
|
|
*
|
|
* @param nodesEdgesVector by reference the adjacency-list
|
|
* @param currNodeEntry the current contracted node.
|
|
* @return true since all modifications are done within the given parameters
|
|
*/
|
|
bool hlRecalculateNeighboursInHlGraph(
|
|
std::vector<HlNodeEntry*> &nodesEdgesVector,
|
|
HlNodeEntry* currNodeEntry) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlRecalculateNeighboursInHlGraph" << endl);
|
|
#endif
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlRecalculateNeighboursInHlGraph" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Creates the Upward- and Downwardgraph from the given HlGraph.
|
|
* The Upward Graph only contains edges (u, v) leading to nodes v
|
|
* having a higher rank than u.
|
|
* The Downward Graph only contains edges (u, v) leading to nodes v
|
|
* having a lower rank than u.
|
|
* Because the HlGraph still contaings original edges and reverse-edges
|
|
* we can make use of this.
|
|
* For searches we only need:
|
|
* - original (forward) edges leading to nodes with a higher rank
|
|
* - reverse (backward) edges leading to nodes with a higher rank
|
|
* (because we actually need forward edges leading to nodes with
|
|
* lower rank and invert them which in turn are reverse edges
|
|
* leading to nodes with higher rank)
|
|
*
|
|
* We still do have both but also we have edges leading to nodes with
|
|
* lower rank.
|
|
* So this function just removes forward and backward-edges leading to
|
|
* nodes with lower rank.
|
|
*
|
|
* @param nodesEdgesVector by reference the adjacency-list
|
|
* @param contractNodeTuple by reference the data-tuple
|
|
of the current node contracted.
|
|
* @param contractNodeId the id of the node to be contracted.
|
|
* @return true since all modifications are done within the given parameters
|
|
*/
|
|
bool hlCreateUpwardAndDownwardHlGraph(std::vector<HlNodeEntry*>
|
|
&nodesEdgesVector) const
|
|
{
|
|
#ifdef USEINFO
|
|
LogInfo("start hlCreateUpwardAndDownwardHlGraph" << endl);
|
|
#endif
|
|
|
|
|
|
#ifdef USEINFO
|
|
size_t graphSize = nodesEdgesVector.size();
|
|
int progress = 0;
|
|
#endif
|
|
|
|
//iterate over whole graph-map
|
|
for (std::vector<HlNodeEntry*>::iterator
|
|
nodesEdgesVectorIter = nodesEdgesVector.begin();
|
|
nodesEdgesVectorIter != nodesEdgesVector.end();
|
|
++nodesEdgesVectorIter)
|
|
{
|
|
HlNodeEntry* currNodeEntry = *nodesEdgesVectorIter;
|
|
|
|
std::vector<HlEdgeEntry*>* currNodeVector =
|
|
currNodeEntry->getEdgesVector();
|
|
|
|
#ifdef USEINFO
|
|
progress++;
|
|
if(progress % getProgressInterval() == 0)
|
|
{
|
|
int currSourceNodeId = currNodeEntry->getNodeId();
|
|
int currRank = currNodeEntry->getRankValue();
|
|
|
|
LogInfo("Current SourceNode: " << currSourceNodeId
|
|
<< " with rank: " << currRank << " has #edges: "
|
|
<< currNodeVector->size() << " nodes left: "
|
|
<< (graphSize - progress) << endl);
|
|
}
|
|
#endif
|
|
|
|
|
|
//iterate over all adjacent nodes and delete edges (u, v)
|
|
// leading to nodes v having a lower rank than u
|
|
for(size_t i = 0; i < currNodeVector->size();)
|
|
{
|
|
//dereference vector-pointer to acces via index
|
|
HlEdgeEntry* currEdge = (*currNodeVector)[i];
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("next edge with targetIndex: "
|
|
<< currEdge->getTargetIndex() << endl);
|
|
#endif
|
|
|
|
if( !currEdge->getIsUpwardOriginal())
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("delete currEdge" << endl);
|
|
#endif
|
|
delete currEdge;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("swap currEdge" << endl);
|
|
#endif
|
|
std::swap((*currNodeVector)[i], currNodeVector->back());
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("pop currEdge" << endl);
|
|
#endif
|
|
currNodeVector->pop_back();
|
|
|
|
//do not increase i because we swapped the last element
|
|
// to the position i and want to get it next
|
|
}else{
|
|
++i;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("after source: " << currSourceNodeId << " with rank: " <<
|
|
currRank << " has #edges: " << currNodeVector->size() << endl);
|
|
#endif
|
|
}
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("finish hlCreateUpwardAndDownwardHlGraph" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Help Function to check whether an edge from hlGraph
|
|
* leads to a node with lower rank then the given Rank.
|
|
*
|
|
* @param nodesEdgesVector by reference the adjacency-list
|
|
* @param currEdgeEntry the current edge to be checked
|
|
* @param sourceNodeRank the rank of the sourceNode of the current edge
|
|
*
|
|
* @return true if the edge leads to a node with a lower rank, false else
|
|
*/
|
|
bool hlIsDownwardsInHlGraph(std::vector<HlNodeEntry*> &nodesEdgesVector,
|
|
HlEdgeEntry* currEdgeEntry, int sourceNodeRank) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlIsDownwardsInHlGraph" << endl);
|
|
#endif
|
|
|
|
bool retVal = false;
|
|
|
|
int currTargetNodeIndex = currEdgeEntry->getTargetIndex();
|
|
|
|
|
|
//get Rank of current node
|
|
HlNodeEntry* currTargetNodeEntry =
|
|
nodesEdgesVector[currTargetNodeIndex];
|
|
int currTargetNodeRank = currTargetNodeEntry->getRankValue();
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("sourceNodeRank: " << sourceNodeRank << " currTargetNodeRank: "
|
|
<< currTargetNodeRank << endl);
|
|
#endif
|
|
|
|
//remove edges if leads to a node with lower rank
|
|
if(sourceNodeRank > currTargetNodeRank)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("true" << endl);
|
|
#endif
|
|
retVal = true;
|
|
}
|
|
#ifdef USEDEBUG
|
|
LogDebug("targetnodeindex: " << currTargetNodeIndex << " with rank: "
|
|
<< currTargetNodeRank
|
|
<< " isDownward: " << retVal << "(0 = false)"<< endl);
|
|
#endif
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlIsDownwardsInHlGraph" << endl);
|
|
#endif
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Gets an OrderedRelation representing an previous exported HlGraph.
|
|
* Transforms it against to an HlGraph for further use.
|
|
*
|
|
* @param hlGraphOrel the orel to be transformed
|
|
* @param nodesEdgesVector by reference the hlGraph to fill
|
|
*
|
|
* @return true since all modifications take place in the given parameters
|
|
*/
|
|
bool hlTransformHlGraphOrelToHlGraph(OrderedRelation* hlGraphOrel,
|
|
std::vector<HlNodeEntry*> &nodesEdgesVector) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlTransformHlGraphOrelToHlGraph" << endl);
|
|
#endif
|
|
|
|
GenericRelationIterator* hlGraphOrelIter = hlGraphOrel->MakeScan();
|
|
|
|
//Get first Tuple
|
|
Tuple* currNode = hlGraphOrelIter->GetNextTuple();
|
|
|
|
HlNodeEntry* currNodeEntry = 0;
|
|
std::vector<HlEdgeEntry*>* currEdgeVector = 0;
|
|
int currSourceId = -1;
|
|
//Iterate over all Tuples
|
|
while(currNode)
|
|
{
|
|
CcInt* currEdgeSource = (CcInt*) currNode->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_HL_GRAPH);
|
|
CcInt* currEdgeTarget = (CcInt*) currNode->GetAttribute(
|
|
HL_INDEX_OF_TARGET_IN_HL_GRAPH);
|
|
CcInt* currEdgeSourceIndex = (CcInt*) currNode->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_INDEX_IN_HL_GRAPH);
|
|
CcInt* currEdgeTargetIndex = (CcInt*) currNode->GetAttribute(
|
|
HL_INDEX_OF_TARGET_INDEX_IN_HL_GRAPH);
|
|
CcInt* currEdgeSourceRank = (CcInt*) currNode->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_RANK_IN_HL_GRAPH);
|
|
CcBool* currEdgeIsForward = (CcBool*) currNode->GetAttribute(
|
|
HL_INDEX_OF_IS_FORWARD_IN_HL_GRAPH);
|
|
CcBool* currEdgeIsReverse = (CcBool*) currNode->GetAttribute(
|
|
HL_INDEX_OF_IS_REVERSE_IN_HL_GRAPH);
|
|
CcInt* currEdgeParentForward = (CcInt*) currNode->GetAttribute(
|
|
HL_INDEX_OF_PARENT_INDEX_FORWARD_IN_HL_GRAPH);
|
|
CcInt* currEdgeParentReverse = (CcInt*) currNode->GetAttribute(
|
|
HL_INDEX_OF_PARENT_INDEX_REVERSE_IN_HL_GRAPH);
|
|
CcReal* currEdgeWeightForward = (CcReal*) currNode->GetAttribute(
|
|
HL_INDEX_OF_WEIGHT_FORWARD_IN_HL_GRAPH);
|
|
CcReal* currEdgeWeightReverse = (CcReal*) currNode->GetAttribute(
|
|
HL_INDEX_OF_WEIGHT_REVERSE_IN_HL_GRAPH);
|
|
|
|
|
|
int currEdgeSourceId = currEdgeSource->GetIntval();
|
|
int currEdgeTargetId = currEdgeTarget->GetIntval();
|
|
|
|
//check if we reached the next source ID, create new nodeEntry then
|
|
// use the previous one else
|
|
if(currSourceId != currEdgeSourceId)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("new source reached, create new vector, new id: "
|
|
<< currEdgeSourceId
|
|
<< " old: " << currSourceId << endl);
|
|
#endif
|
|
|
|
currNodeEntry = new HlNodeEntry();
|
|
currEdgeVector = new std::vector<HlEdgeEntry*>();
|
|
|
|
currNodeEntry->setNodeId(currEdgeSourceId);
|
|
currNodeEntry->setRankValue(currEdgeSourceRank->GetIntval());
|
|
currNodeEntry->setEdgesVector(currEdgeVector);
|
|
|
|
//also add it to map
|
|
nodesEdgesVector[currEdgeSourceIndex->GetIntval()] =
|
|
currNodeEntry;
|
|
|
|
//set currSourceId to next available source
|
|
currSourceId = currEdgeSourceId;
|
|
}
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("next edge (" << currEdgeSourceId
|
|
<< ", " << currEdgeTargetId << " from while" << endl);
|
|
#endif
|
|
|
|
//check whether the current edge leads to a valid target
|
|
//in case of the highest rank vertext there are no edges
|
|
// outgoing from that node (because there are no other nodes having
|
|
// higher rank
|
|
//but we still need the node to transform into hlGraph
|
|
// thats why we look for the target id beeing not -1
|
|
// in case of -1 we assume to have the highest rank vertext
|
|
// and will not do add any HlEdgeEntries
|
|
if(currEdgeTargetId != -1)
|
|
{
|
|
HlEdgeEntry* currSourceEdgeEntry = new HlEdgeEntry();
|
|
currSourceEdgeEntry->setTargetIndex(
|
|
currEdgeTargetIndex->GetIntval());
|
|
currSourceEdgeEntry->setIsForward(
|
|
currEdgeIsForward->GetBoolval());
|
|
currSourceEdgeEntry->setIsReverse(
|
|
currEdgeIsReverse->GetBoolval());
|
|
currSourceEdgeEntry->setParentIndexForward(
|
|
currEdgeParentForward->GetIntval());
|
|
currSourceEdgeEntry->setParentIndexReverse(
|
|
currEdgeParentReverse->GetIntval());
|
|
currSourceEdgeEntry->setWeightForward(
|
|
currEdgeWeightForward->GetRealval());
|
|
currSourceEdgeEntry->setWeightReverse(
|
|
currEdgeWeightReverse->GetRealval());
|
|
currEdgeVector->push_back(currSourceEdgeEntry);
|
|
}
|
|
|
|
|
|
//get next Tuple from Orel
|
|
currNode->DeleteIfAllowed();
|
|
currNode = 0;
|
|
currNode = hlGraphOrelIter->GetNextTuple();
|
|
}
|
|
delete hlGraphOrelIter;
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlTransformHlGraphOrelToHlGraph" << endl);
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Gets the hlGraph and frees all its containing elements by iterating
|
|
* over it and its subelements and deleting them.
|
|
*
|
|
* @param nodesEdgesVector the hlGraph to be deleted
|
|
*
|
|
* @return true since all modifications take place in the given parameters
|
|
*/
|
|
bool hlFreeHlGraph(std::vector<HlNodeEntry*> &nodesEdgesVector) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlFreeHlGraph" << endl);
|
|
#endif
|
|
|
|
for (std::vector<HlNodeEntry*>::iterator
|
|
nodesEdgesVectorIter = nodesEdgesVector.begin();
|
|
nodesEdgesVectorIter != nodesEdgesVector.end();
|
|
++nodesEdgesVectorIter)
|
|
{
|
|
HlNodeEntry* currHlNodeEntry = (*nodesEdgesVectorIter);
|
|
|
|
std::vector<HlEdgeEntry*>* currHlEdgeEntries =
|
|
currHlNodeEntry->getEdgesVector();
|
|
|
|
for (std::vector<HlEdgeEntry*>::iterator
|
|
currHlEdgeEntriesIter = currHlEdgeEntries->begin();
|
|
currHlEdgeEntriesIter != currHlEdgeEntries->end();
|
|
++currHlEdgeEntriesIter)
|
|
{
|
|
HlEdgeEntry* currHlEdgeEntry = (*currHlEdgeEntriesIter);
|
|
delete currHlEdgeEntry;
|
|
}
|
|
|
|
delete currHlEdgeEntries;
|
|
delete currHlNodeEntry;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlFreeHlGraph" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Gets the searchTree and frees all its containing elements by iterating
|
|
* over it and deleting them.
|
|
*
|
|
* @param searchTree the searchTree to be deleted
|
|
*
|
|
* @return true since all modifications take place in the given parameters
|
|
*/
|
|
bool hlFreeSearchTree(std::map<int, ChNode*> &searchTree) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlFreeSearchTree" << endl);
|
|
#endif
|
|
|
|
for (std::map<int, ChNode*>::iterator
|
|
searchTreeIter = searchTree.begin();
|
|
searchTreeIter != searchTree.end();
|
|
++searchTreeIter)
|
|
{
|
|
ChNode* currChNode = (*searchTreeIter).second;
|
|
delete currChNode;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlFreeSearchTree" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Processes either a CH (isChElseHl = true) or a HL Search (else)
|
|
* for the given source and target.
|
|
*
|
|
* Basically it performs a Bi-Directional Dijkstra (a forward search from
|
|
* source and a reverse search from target).
|
|
* By this both searches have their on distance-queue. The search having the
|
|
* next node to scan with the minimum distance of both queues is
|
|
* processed next.
|
|
* This way both search-spaced expand equally.
|
|
*
|
|
* In case of both HL and CH Search are proceeded until both queues are
|
|
* empty. If one queue gets empty the other search still is continued.
|
|
*
|
|
* In case of CH search theres an additional break condition.
|
|
* If the search distance of an (either forward or reverse) search does
|
|
* exceed the shortestPath found so far this search is aborted. The other
|
|
* search keeps proceeding.
|
|
*
|
|
* In case of HL search theres no such additional break condition.
|
|
* Target of an HL search is to retrieve the full search tree of a node.
|
|
* That way one should use the same nodeId as source and target as well.
|
|
*
|
|
* Elsewise the behaviour of an CH search is as follows for retrieving the
|
|
* shortest path.
|
|
* If theres a node visited by both (forward and reverse) searches,
|
|
* the distances of both searches to this node are summed up and
|
|
* if the sum is the smallest distance found so far this node will
|
|
* be stored as current minimum distance.
|
|
* After both searches have finished the currentMinimumDistance is
|
|
* retrieved as shortest path from source to target.
|
|
*
|
|
* As result it returns a tuple containing
|
|
* - At first the NodeId of the hub found on the shortest path
|
|
* during Bi-Directional Dijkstra Search/ CH Search.
|
|
* May this is -1 if theres no shortest path or when a HL-Search was
|
|
* started.
|
|
* - At second the length of this shortest path if found, 0.0 else.
|
|
* - At third the search tree build up so far during the searches.
|
|
* Using this tree one can retrieve the single edges of the shortest path.
|
|
* On HL Queries this is the valid Label of the given node as desired.
|
|
*
|
|
* @param nodesEdgesVector by reference the adjacency-list
|
|
* @param source the sourceNodeId
|
|
* @param target the targetnodeId
|
|
* @param isChElseHl indicates whether we perform a CH Search or HL Search
|
|
* @return the result Tuple as described above.
|
|
*/
|
|
std::tuple<int, double, std::map<int, ChNode*>> hlDoCHSearch(
|
|
std::vector<HlNodeEntry*> &nodesEdgesVector,
|
|
int source, int target, bool isChElseHl) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlDoCHSearch" << endl);
|
|
#endif
|
|
|
|
|
|
//define returnValue
|
|
std::map<int, ChNode*> searchTree;
|
|
|
|
|
|
//the Predecessor of source/ target itself does not exists
|
|
// and the distance to the nodes themselves is 0.0
|
|
//predecessor must not be -1 since this an indicator for not visited
|
|
// nodes
|
|
int initPredecessorIndex = -2;
|
|
double initDistance = 0.0;
|
|
|
|
|
|
|
|
|
|
//get source and target NodeIndex
|
|
HlNodeEntry* sourceNodeEntry = 0;
|
|
HlNodeEntry* targetNodeEntry = 0;
|
|
int sourceNodeIndex = -1;
|
|
int targetNodeIndex = -1;
|
|
|
|
for(uint i = 0; i< nodesEdgesVector.size(); i++)
|
|
{
|
|
HlNodeEntry* currNodeEntry = nodesEdgesVector[i];
|
|
|
|
if(currNodeEntry->getNodeId() == source)
|
|
{
|
|
sourceNodeEntry = currNodeEntry;
|
|
sourceNodeIndex = i;
|
|
|
|
//check if target still has been found, abort if true
|
|
if(targetNodeEntry)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(currNodeEntry->getNodeId() == target)
|
|
{
|
|
targetNodeEntry = currNodeEntry;
|
|
targetNodeIndex = i;
|
|
|
|
//check if source still has been found, abort if true
|
|
if(sourceNodeEntry)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!sourceNodeEntry || !targetNodeEntry)
|
|
{
|
|
#ifdef USEERROR
|
|
LogError("Fehler, source or target not found" << endl);
|
|
#endif
|
|
|
|
return std::make_tuple(-1, 0.0, searchTree);
|
|
}
|
|
|
|
//if source = target and isCH theres nothing to search
|
|
if(source == target && isChElseHl)
|
|
{
|
|
std::cout <<
|
|
"Warn. Given Source and Target are qual, no path to retrieve."
|
|
<< endl;
|
|
return std::make_tuple(sourceNodeIndex, 0.0, searchTree);
|
|
}
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("prepare forward search" << endl);
|
|
#endif
|
|
|
|
//prepare forward search
|
|
// format is double, int, int -> dist, nodeIndex, predecessorIndex
|
|
PriorityQueueTypeForwardSearch forwardQueue;
|
|
|
|
//add source itself to searchtree with distance 0.0
|
|
ChNode* sourceChNode = new ChNode();
|
|
sourceChNode->setDistForward(initDistance);
|
|
sourceChNode->setPredecessorIndexForward(initPredecessorIndex);
|
|
|
|
searchTree.insert(std::pair<int, ChNode*>(sourceNodeIndex,
|
|
sourceChNode));
|
|
|
|
//get outgoing edges from source
|
|
std::vector<HlEdgeEntry*>* currNodeVectorSource =
|
|
sourceNodeEntry->getEdgesVector();
|
|
|
|
//init forward queue
|
|
bool isForwardSearch = true;
|
|
hlCHSearchScanNewVertices(forwardQueue, searchTree,
|
|
currNodeVectorSource, initDistance, isForwardSearch, sourceNodeIndex);
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("prepare reverse search" << endl);
|
|
#endif
|
|
|
|
//prepare reverse search
|
|
// format is double, int, int -> dist, nodeIndex, predecessorIndex
|
|
PriorityQueueTypeForwardSearch reverseQueue;
|
|
|
|
//add target itself to searchtree with distance 0.0
|
|
// but check if source and target are equal
|
|
// use existing chNode object then
|
|
// only occurs on hlMode (else a previous return had been done
|
|
ChNode* targetChNode = 0;
|
|
if(source == target)
|
|
{
|
|
targetChNode = sourceChNode;
|
|
|
|
targetChNode->setDistReverse(initDistance);
|
|
targetChNode->setPredecessorIndexReverse(initPredecessorIndex);
|
|
}else{
|
|
targetChNode = new ChNode();
|
|
targetChNode->setDistReverse(initDistance);
|
|
targetChNode->setPredecessorIndexReverse(initPredecessorIndex);
|
|
|
|
searchTree.insert(std::pair<int, ChNode*>(targetNodeIndex,
|
|
targetChNode));
|
|
}
|
|
|
|
//get outgoing edges from target
|
|
std::vector<HlEdgeEntry*>* currNodeVectorTarget =
|
|
targetNodeEntry->getEdgesVector();
|
|
|
|
//init reverse queue
|
|
hlCHSearchScanNewVertices(reverseQueue, searchTree,
|
|
currNodeVectorTarget, initDistance, !isForwardSearch, targetNodeIndex);
|
|
|
|
|
|
|
|
|
|
//do search until ready
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("do iterative CH search" << endl);
|
|
#endif
|
|
|
|
|
|
//get top element of forward queue
|
|
double currDistToSourceForward = 0.0;
|
|
int currNodeIndexForward = -1;
|
|
int currNodeIdForward = -1;
|
|
int currPredecessorIndexForward = -1;
|
|
HlNodeEntry* currNodeEntryForward = 0;
|
|
|
|
if(!forwardQueue.empty())
|
|
{
|
|
//get data
|
|
QueuePairTypeForwardSearch currForwardQueuePair =
|
|
forwardQueue.top();
|
|
|
|
//do not pop yet
|
|
|
|
currDistToSourceForward = currForwardQueuePair.first;
|
|
std::pair<int, int> currTupleQueueForward =
|
|
currForwardQueuePair.second;
|
|
currNodeIndexForward = currTupleQueueForward.first;
|
|
currPredecessorIndexForward = currTupleQueueForward.second;
|
|
|
|
currNodeEntryForward = nodesEdgesVector[currNodeIndexForward];
|
|
currNodeIdForward = currNodeEntryForward->getNodeId();
|
|
}
|
|
|
|
//get top element of reverse queue
|
|
double currDistToTargetReverse = 0.0;
|
|
int currNodeIndexReverse = -1;
|
|
int currNodeIdReverse = -1;
|
|
int currPredecessorIndexReverse = -1;
|
|
HlNodeEntry* currNodeEntryReverse = 0;
|
|
|
|
if(!reverseQueue.empty())
|
|
{
|
|
//get data
|
|
QueuePairTypeForwardSearch currReverseQueuePair =
|
|
reverseQueue.top();
|
|
|
|
//do not pop yet
|
|
|
|
currDistToTargetReverse = currReverseQueuePair.first;
|
|
std::pair<int, int> currTupleQueueReverse =
|
|
currReverseQueuePair.second;
|
|
currNodeIndexReverse = currTupleQueueReverse.first;
|
|
currPredecessorIndexReverse = currTupleQueueReverse.second;
|
|
|
|
currNodeEntryReverse = nodesEdgesVector[currNodeIndexReverse];
|
|
currNodeIdReverse = currNodeEntryReverse->getNodeId();
|
|
}
|
|
|
|
|
|
int currMinShortestPathHubIndex = -1;
|
|
double currMinShortestPathDist = 0.0;
|
|
|
|
//do while queues are not empty
|
|
//if other break-conditions are fullfilled we just clear the related
|
|
// queue such that it gets empty
|
|
while((!forwardQueue.empty() || !reverseQueue.empty()))
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("next queue candidate are: fwd: "
|
|
<< currNodeIdForward
|
|
<< " with dist: " << currDistToSourceForward
|
|
<< " and rvs: " << currNodeIdReverse << " with dist: "
|
|
<< currDistToTargetReverse << endl);
|
|
#endif
|
|
|
|
//check which queue has the smaller element
|
|
//a queue also has the smaller element if the other queue is empty
|
|
if( (reverseQueue.empty() )
|
|
|| ( currDistToSourceForward <= currDistToTargetReverse
|
|
&& !forwardQueue.empty() ) )
|
|
{
|
|
//forward search
|
|
|
|
//exit if currNodeIndexForward was not found
|
|
if(!currNodeEntryForward)
|
|
{
|
|
#ifdef USEERROR
|
|
LogError("error while retrieving currForwardNode from hlGraph "
|
|
<< currNodeIdForward << endl);
|
|
#endif
|
|
}
|
|
|
|
|
|
//get data
|
|
std::vector<HlEdgeEntry*>* currNodeVectorForward =
|
|
currNodeEntryForward->getEdgesVector();
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("next top min forward: " << currNodeIdForward << endl);
|
|
#endif
|
|
|
|
//check whether the current node still exists within
|
|
// search tree by reverse search
|
|
// if yes edit the existing object and check for new
|
|
// shortestPath
|
|
//if it exists in search tree but by forward search,
|
|
// we ignore this still visited node
|
|
bool isStillVisitedByReverse = false;
|
|
bool isStillVisitedByForward = false;
|
|
|
|
std::map<int, ChNode*>::iterator searchTreeIter =
|
|
searchTree.find(currNodeIndexForward);
|
|
|
|
if(searchTreeIter != searchTree.end())
|
|
{
|
|
ChNode* currChNode = (*searchTreeIter).second;
|
|
|
|
|
|
//chech whether node found is still from forward search
|
|
if(currChNode->getPredecessorIndexForward() != -1)
|
|
{
|
|
isStillVisitedByForward = true;
|
|
}
|
|
|
|
//chech whether node found is still from reverse search
|
|
if(currChNode->getPredecessorIndexReverse() != -1)
|
|
{
|
|
isStillVisitedByReverse = true;
|
|
}
|
|
}
|
|
|
|
//only proceed if is not still visited by forward search
|
|
if(!isStillVisitedByForward)
|
|
{
|
|
//if is still visited by opposite search check
|
|
// for shortest path else add to search tree
|
|
if(isStillVisitedByReverse)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("hub found: " << currNodeIdForward << endl);
|
|
#endif
|
|
|
|
//edit entry and check for new shortestPath
|
|
ChNode* currForwardChNode = (*searchTreeIter).second;
|
|
currForwardChNode->setDistForward(
|
|
currDistToSourceForward);
|
|
currForwardChNode->setPredecessorIndexForward(
|
|
currPredecessorIndexForward);
|
|
|
|
double shortestPathCandidateDist =
|
|
currDistToSourceForward
|
|
+ currForwardChNode->getDistReverse();
|
|
|
|
//check if a hub still has been found or if the current
|
|
// hub provides a shorter path than found so far
|
|
if(currMinShortestPathHubIndex == -1 ||
|
|
shortestPathCandidateDist < currMinShortestPathDist)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("new shorter path with length: "
|
|
<< shortestPathCandidateDist << endl);
|
|
#endif
|
|
|
|
currMinShortestPathHubIndex = currNodeIndexForward;
|
|
currMinShortestPathDist = shortestPathCandidateDist;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("insert new into searchTree id:"
|
|
<< currNodeIdForward
|
|
<< " with dist: " << currDistToSourceForward
|
|
<< " and predecessor index "
|
|
<< currPredecessorIndexForward
|
|
<< endl);
|
|
#endif
|
|
|
|
ChNode* currForwardChNode = new ChNode();
|
|
currForwardChNode->setDistForward(
|
|
currDistToSourceForward);
|
|
currForwardChNode->setPredecessorIndexForward(
|
|
currPredecessorIndexForward);
|
|
|
|
searchTree.insert(std::pair<int, ChNode*>(
|
|
currNodeIndexForward, currForwardChNode));
|
|
}
|
|
|
|
//scan new vertices for inserting into queue
|
|
hlCHSearchScanNewVertices(forwardQueue, searchTree,
|
|
currNodeVectorForward, currDistToSourceForward,
|
|
isForwardSearch, currNodeIndexForward);
|
|
}
|
|
|
|
//pop current top element from queue to get next
|
|
forwardQueue.pop();
|
|
|
|
//check whether its empty
|
|
if(!forwardQueue.empty())
|
|
{
|
|
//get data
|
|
QueuePairTypeForwardSearch currForwardQueuePair =
|
|
forwardQueue.top();
|
|
|
|
currDistToSourceForward = currForwardQueuePair.first;
|
|
std::pair<int, int> currTupleQueueForward =
|
|
currForwardQueuePair.second;
|
|
currNodeIndexForward = currTupleQueueForward.first;
|
|
currPredecessorIndexForward =
|
|
currTupleQueueForward.second;
|
|
|
|
currNodeEntryForward =
|
|
nodesEdgesVector[currNodeIndexForward];
|
|
currNodeIdForward = currNodeEntryForward->getNodeId();
|
|
|
|
//check whether we are in CH mode and if the distance
|
|
// of the next top element exceeds the current shortest
|
|
// path found so far
|
|
//also check that there still exists a shortet path hub
|
|
//clear the queue then to stop the search
|
|
if(isChElseHl && currMinShortestPathHubIndex != -1 &&
|
|
currDistToSourceForward >= currMinShortestPathDist)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("next top node id:" << currNodeIdForward
|
|
<< " with distToSource: " << currDistToSourceForward
|
|
<< " exceeds currMinDist: "
|
|
<< currMinShortestPathDist << endl);
|
|
#endif
|
|
|
|
//clear queue by reassigning it
|
|
forwardQueue = PriorityQueueTypeForwardSearch();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//reverse search
|
|
|
|
//exit if currNodeIdReverse was not found
|
|
if(!currNodeEntryReverse)
|
|
{
|
|
#ifdef USEERROR
|
|
LogError("error while retrieving currReverseNode from hlGraph "
|
|
<< currNodeIdReverse << endl);
|
|
#endif
|
|
}
|
|
|
|
|
|
//get data
|
|
std::vector<HlEdgeEntry*>* currNodeVectorReverse =
|
|
currNodeEntryReverse->getEdgesVector();
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("next top min reverse: " << currNodeIdReverse << endl);
|
|
#endif
|
|
|
|
//check whether the current node still exists within
|
|
// search tree by forward search
|
|
// if yes edit the existing object and check for new
|
|
// shortestPath
|
|
//if it exists in search tree but by reverse search,
|
|
// we ignore this still visited node
|
|
bool isStillVisitedByReverse = false;
|
|
bool isStillVisitedByForward = false;
|
|
|
|
std::map<int, ChNode*>::iterator searchTreeIter =
|
|
searchTree.find(currNodeIndexReverse);
|
|
|
|
if(searchTreeIter != searchTree.end())
|
|
{
|
|
ChNode* currChNode = (*searchTreeIter).second;
|
|
|
|
//chech whether node found is still from reverse search
|
|
if(currChNode->getPredecessorIndexReverse() != -1)
|
|
{
|
|
isStillVisitedByReverse = true;
|
|
}
|
|
|
|
//chech whether node found is still from forward search
|
|
if(currChNode->getPredecessorIndexForward() != -1)
|
|
{
|
|
isStillVisitedByForward = true;
|
|
}
|
|
}
|
|
|
|
//if is still visited by opposite search check
|
|
// for shortest path else add to search tree
|
|
if(!isStillVisitedByReverse)
|
|
{
|
|
if(isStillVisitedByForward)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("hub found: " << currNodeIdReverse << endl);
|
|
#endif
|
|
|
|
//edit entry and check for new shortestPath
|
|
ChNode* currReverseChNode = (*searchTreeIter).second;
|
|
currReverseChNode->setDistReverse(
|
|
currDistToTargetReverse);
|
|
currReverseChNode->setPredecessorIndexReverse(
|
|
currPredecessorIndexReverse);
|
|
|
|
double shortestPathCandidateDist =
|
|
currDistToTargetReverse
|
|
+ currReverseChNode->getDistForward();
|
|
|
|
//check if a hub still has been found or if the current
|
|
// hub provides a shorter path than found so far
|
|
if(currMinShortestPathHubIndex == -1
|
|
|| shortestPathCandidateDist < currMinShortestPathDist)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("new shorter path with length: "
|
|
<< shortestPathCandidateDist << endl);
|
|
#endif
|
|
|
|
currMinShortestPathHubIndex = currNodeIndexReverse;
|
|
currMinShortestPathDist = shortestPathCandidateDist;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("insert new into searchTree id:"
|
|
<< currNodeIdReverse
|
|
<< " with dist: " << currDistToTargetReverse
|
|
<< " and predecessor "
|
|
<< currPredecessorIndexReverse
|
|
<< endl);
|
|
#endif
|
|
|
|
ChNode* currReverseChNode = new ChNode();
|
|
currReverseChNode->setDistReverse(
|
|
currDistToTargetReverse);
|
|
currReverseChNode->setPredecessorIndexReverse(
|
|
currPredecessorIndexReverse);
|
|
|
|
searchTree.insert(std::pair<int, ChNode*>(
|
|
currNodeIndexReverse, currReverseChNode));
|
|
}
|
|
|
|
//scan new vertices for inserting into queue
|
|
hlCHSearchScanNewVertices(reverseQueue, searchTree,
|
|
currNodeVectorReverse, currDistToTargetReverse,
|
|
!isForwardSearch, currNodeIndexReverse);
|
|
}
|
|
|
|
//pop current top element from queue to get next
|
|
reverseQueue.pop();
|
|
|
|
//check whether its empty
|
|
if(!reverseQueue.empty())
|
|
{
|
|
//get data
|
|
QueuePairTypeForwardSearch currReverseQueuePair =
|
|
reverseQueue.top();
|
|
//do not pop it yet, we need to handle it within next
|
|
// iteration
|
|
|
|
currDistToTargetReverse = currReverseQueuePair.first;
|
|
std::pair<int, int> currTupleQueueReverse =
|
|
currReverseQueuePair.second;
|
|
currNodeIndexReverse = currTupleQueueReverse.first;
|
|
currPredecessorIndexReverse =
|
|
currTupleQueueReverse.second;
|
|
|
|
currNodeEntryReverse =
|
|
nodesEdgesVector[currNodeIndexReverse];
|
|
|
|
currNodeIdReverse = currNodeEntryReverse->getNodeId();
|
|
|
|
//check whether we are in CH mode and if the distance
|
|
// of the next top element exceeds the current shortest
|
|
// path found so far
|
|
//also check that there still exists a shortet path hub
|
|
//clear the queue then to stop the search
|
|
if(isChElseHl && currMinShortestPathHubIndex != -1 &&
|
|
currDistToTargetReverse >= currMinShortestPathDist)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("next top node id:" << currNodeIdReverse
|
|
<< " with distToTarget: " << currDistToTargetReverse
|
|
<< " exceeds currMinDist: "
|
|
<< currMinShortestPathDist << endl);
|
|
#endif
|
|
|
|
//clear queue by reassigning it
|
|
forwardQueue = PriorityQueueTypeForwardSearch();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//search finished build result type
|
|
std::tuple<int, double, std::map<int, ChNode*>> retVal =
|
|
std::make_tuple(currMinShortestPathHubIndex,
|
|
currMinShortestPathDist, searchTree);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlDoCHSearch" << endl);
|
|
#endif
|
|
|
|
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
/*
|
|
* Ierates over all outgoing edges and may adds or merge them into
|
|
* the given forwardQueueMultimap. Edges are only added if they do not
|
|
* have been still visited due to previous iterations.
|
|
* Edges are merged if they still exist within the queue but are on a
|
|
* shorter path to the specific target node than it was inserted into
|
|
* the queue before.
|
|
* To check whether a node still has been visited we make a lookup
|
|
* within the searchTree.
|
|
*
|
|
* @param currQueue by reference the queue where to maybe insert or merge
|
|
* the given edges
|
|
* @param searchTree the search tree by reference build up so far
|
|
* @param nodesEdges the hlGraph for getting nodeIds
|
|
* @param currNodeVector the edges to be inserted or merged
|
|
* @param distanceSoFar the search-distance of the current node
|
|
* being source of the given edges
|
|
* @param isForward indicates whether we are on forward or reverse search
|
|
* @param predecessorIndex the index within hlGraph of the predecessor
|
|
* @return true since all modifications are done within the given parameters
|
|
*/
|
|
bool hlCHSearchScanNewVertices(PriorityQueueTypeForwardSearch &currQueue,
|
|
std::map<int, ChNode*> &searchTree,
|
|
std::vector<HlEdgeEntry*>* currNodeVector, double distanceSoFar,
|
|
bool isForward, int predecessorIndex) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlCHSearchScanNewVertices" << endl);
|
|
#endif
|
|
|
|
//iterate over all edges
|
|
for (std::vector<HlEdgeEntry*>::iterator
|
|
currNodeVectorIter = currNodeVector->begin();
|
|
currNodeVectorIter != currNodeVector->end();
|
|
++currNodeVectorIter)
|
|
{
|
|
HlEdgeEntry* currEdgeEntry =
|
|
*currNodeVectorIter;
|
|
|
|
int currTargetIndex = -1;
|
|
double currWeight = 0.0;
|
|
|
|
//check whether edge relates to the desired search
|
|
// or if theres no related edge to scan
|
|
if(isForward && currEdgeEntry->getIsForward())
|
|
{
|
|
currTargetIndex = currEdgeEntry->getTargetIndex();
|
|
currWeight = currEdgeEntry->getWeightForward();
|
|
}
|
|
else if(!isForward && currEdgeEntry->getIsReverse())
|
|
{
|
|
currTargetIndex = currEdgeEntry->getTargetIndex();
|
|
currWeight = currEdgeEntry->getWeightReverse();
|
|
}else{
|
|
#ifdef USEDEBUG
|
|
LogDebug("current edge not related to the desired direction"
|
|
<< endl);
|
|
#endif
|
|
continue;
|
|
}
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("scan next edge for inserting into queue, targetIndex: "
|
|
<< currTargetIndex << endl);
|
|
#endif
|
|
|
|
//check whether current target node still has been visited
|
|
// by current search direction (it may still exists by
|
|
// the opposite search)x
|
|
bool isStillVisited = false;
|
|
|
|
std::map<int, ChNode*>::iterator searchTreeIter =
|
|
searchTree.find(currTargetIndex);
|
|
|
|
if(searchTreeIter != searchTree.end())
|
|
{
|
|
ChNode* currChNode = (*searchTreeIter).second;
|
|
|
|
//in case of start end end nodes of the CH Search
|
|
// the predecessor of these both nodes is -2
|
|
//so it is safe to compare predecessor to -1 here
|
|
if( ( isForward &&
|
|
currChNode->getPredecessorIndexForward() != -1)
|
|
|| (!isForward &&
|
|
currChNode->getPredecessorIndexReverse() != -1) )
|
|
{
|
|
isStillVisited = true;
|
|
}
|
|
}
|
|
|
|
//only add to search tree if not has been still visited
|
|
//just skip else
|
|
if(!isStillVisited)
|
|
{
|
|
double distFromSourceToCurrTarget = distanceSoFar + currWeight;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("insert into queue index: " << currTargetIndex
|
|
<< " with dist from source: " << distFromSourceToCurrTarget
|
|
<< " with predecessorIndex: " << predecessorIndex
|
|
<< endl);
|
|
#endif
|
|
|
|
currQueue.push(std::make_pair(
|
|
distFromSourceToCurrTarget,
|
|
std::make_pair(currTargetIndex, predecessorIndex)
|
|
));
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlCHSearchScanNewVertices" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Extracts the shortestPath from the given search tree and alo
|
|
* resolves shortcut edges to the underlying original edges
|
|
* and adds all original osm edges in their order from source to
|
|
* target to the given Relation.
|
|
*
|
|
* @param shortestPathHubIndex the hub nodeIndex
|
|
* on the shortest path from s to t
|
|
* @param nodesEdgesVector the hlGraph by reference used for
|
|
* resolving shortcut edges
|
|
* @param searchTree the search tree by reference build up so far
|
|
* @param edgesSourceOrel the osm graph used to extract osm edges
|
|
* @param shortestPathRel the resulting relation containing shortest path
|
|
* @return true since all modifications are done within the given parameters
|
|
*/
|
|
bool hlResolveShortestPathFromSearchTree(int shortestPathHubIndex,
|
|
std::vector<HlNodeEntry*> &nodesEdgesVector,
|
|
std::map<int, ChNode*> &searchTree, OrderedRelation* edgesSourceOrel,
|
|
Relation* shortestPathRel) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlResolveShortestPathFromSearchTree" << endl);
|
|
#endif
|
|
|
|
//if searchtree does not have at least three elements (s, v, t) theres
|
|
// no path to retrieve
|
|
if(searchTree.size() < 2)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Not enough hops for creating edges." << endl);
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
//prepare path vectors
|
|
std::vector<int> shortestPathForward;
|
|
std::vector<int> shortestPathReverse;
|
|
|
|
bool isForward = true;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("forward resolve from searchTree" << endl);
|
|
#endif
|
|
|
|
hlResolveShortestPathFromSearchTreeToVector(searchTree,
|
|
shortestPathForward, shortestPathHubIndex, isForward);
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("reverse resolve from searchTree" << endl);
|
|
#endif
|
|
|
|
hlResolveShortestPathFromSearchTreeToVector(searchTree,
|
|
shortestPathReverse, shortestPathHubIndex, !isForward);
|
|
|
|
//since the forward vector was traversed in reverse manner we need
|
|
// to invert it
|
|
//since the reverse vector was traversed in reverse manner and
|
|
// it was reverse search it still has the right order
|
|
|
|
int currUIndex = -1;
|
|
int currWIndex = -1;
|
|
|
|
LogDebug("iterate forward edges" << endl);
|
|
|
|
//iterate forward edges and resolve by OSM-Edges and add to result rel
|
|
for (std::vector<int>::reverse_iterator
|
|
shortestPathForwardIter = shortestPathForward.rbegin();
|
|
shortestPathForwardIter != shortestPathForward.rend();
|
|
++shortestPathForwardIter)
|
|
{
|
|
currWIndex = (*shortestPathForwardIter);
|
|
|
|
|
|
//resolve shortcut and get osm edge (if its not the first call)
|
|
if(currUIndex != -1)
|
|
{
|
|
hlResolveShortcutAndAddToOrel(currUIndex, currWIndex,
|
|
nodesEdgesVector, shortestPathRel, edgesSourceOrel, isForward);
|
|
}
|
|
|
|
//go to next edge
|
|
currUIndex = currWIndex;
|
|
}
|
|
|
|
currUIndex = -1;
|
|
currWIndex = -1;
|
|
|
|
|
|
LogDebug("iterate reverse edges" << endl);
|
|
|
|
//iterate reverse edges and resolve by OSM-Edges and add to result Orel
|
|
for (std::vector<int>::iterator
|
|
shortestPathReverseIter = shortestPathReverse.begin();
|
|
shortestPathReverseIter != shortestPathReverse.end();
|
|
++shortestPathReverseIter)
|
|
{
|
|
currWIndex = (*shortestPathReverseIter);
|
|
|
|
|
|
//resolve shortcut and get osm edge (if its not the first call)
|
|
if(currUIndex != -1)
|
|
{
|
|
hlResolveShortcutAndAddToOrel(currUIndex, currWIndex,
|
|
nodesEdgesVector, shortestPathRel, edgesSourceOrel,
|
|
!isForward);
|
|
}
|
|
|
|
//go to next edge
|
|
currUIndex = currWIndex;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlResolveShortestPathFromSearchTree" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Traverses the searchTree in a reverse manner such that we get the
|
|
* shortestPath of the specific search to the given hubId.
|
|
*
|
|
* @param forwardQueueMultimap the quere where to maybe insert or merge
|
|
* the given edges
|
|
* @param searchTree the search tree by reference
|
|
* @param shortestPathVector by reference the container to
|
|
store shortest path edges
|
|
* @param shortestPathHubIndex the hubIndex of the shortest path
|
|
* @param isForward indicates whether we are on forward or reverse search
|
|
* @return true since all modifications are done within the given parameters
|
|
*/
|
|
bool hlResolveShortestPathFromSearchTreeToVector(std::map<int, ChNode*>
|
|
&searchTree, std::vector<int> &shortestPathVector,
|
|
int shortestPathHubIndex, bool isForward) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlResolveShortestPathFromSearchTreeToVector" << endl);
|
|
#endif
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("add shortestPathHubIndex from search tree to forward vector: "
|
|
<< shortestPathHubIndex << " while isForward: " << isForward << endl);
|
|
#endif
|
|
|
|
//insert hub to path vector
|
|
shortestPathVector.push_back(shortestPathHubIndex);
|
|
|
|
|
|
std::map<int, ChNode*>::iterator searchTreeIter =
|
|
searchTree.find(shortestPathHubIndex);
|
|
|
|
int currPredecessorIndex = -2;
|
|
|
|
//resolve forward search
|
|
while(searchTreeIter != searchTree.end())
|
|
{
|
|
//get next node
|
|
ChNode* currNode = (*searchTreeIter).second;
|
|
|
|
if(isForward)
|
|
{
|
|
currPredecessorIndex = currNode->getPredecessorIndexForward();
|
|
}else{
|
|
currPredecessorIndex = currNode->getPredecessorIndexReverse();
|
|
}
|
|
|
|
//check whether currPredecessorId = -2 which means were done
|
|
// because we reached the actual source or target
|
|
if(currPredecessorIndex != -2)
|
|
{
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("add next node from search tree to vector: "
|
|
<< currPredecessorIndex << endl);
|
|
#endif
|
|
|
|
//add next node to vector
|
|
shortestPathVector.push_back(currPredecessorIndex);
|
|
}
|
|
|
|
//find next node
|
|
searchTreeIter = searchTree.find(currPredecessorIndex);
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlResolveShortestPathFromSearchTreeToVector" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Gets the edge for the given endpoints u and w and checks whether it
|
|
* is a shortcut. If yes it calls the methode itself recursively.
|
|
* If not the both underlying edges are added to the given vector.
|
|
* The edges are inserted in forward direction u -> w.
|
|
*
|
|
* Because we sparsed the hlGraph during creation of upward and downward
|
|
* graphs the underlying edges/ shortcuts of an shortcut from u via v to w
|
|
* need to be found in different direction. Naturally v always has a
|
|
* lower rank than u and w as well. So we can find the underlying edge
|
|
* u to v as reverse edge stored at v in the hlGrapg and v to w as
|
|
* forward edge stored with v. This is valid for both, the forward array
|
|
* and the backward array as well.
|
|
*
|
|
* @param nodeUIndex the start nodeIndex of the currnt edge
|
|
* @param nodeWIndex the target nodeIndex of the currnt edge
|
|
* @param nodesEdgesVector the search tree by reference
|
|
* @param resultEdgesRel the resulting rel filled with shortest path edges
|
|
* @param edgesSourceOrel the osm graph used to extract osm edges
|
|
* @param isForward indicates whether we want to retrieve an forward
|
|
* or reverse edeg
|
|
* @return true since all modifications are done within the given parameters
|
|
*/
|
|
bool hlResolveShortcutAndAddToOrel(int currUIndex, int currWIndex,
|
|
std::vector<HlNodeEntry*> &nodesEdgesVector,
|
|
Relation* resultEdgesRel, OrderedRelation* edgesSourceOrel,
|
|
bool isForward) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlResolveShortcutAndAddToOrel" << endl);
|
|
#endif
|
|
|
|
//if we want a reverse edge we need to search for it at the target node
|
|
int tmpLookupNodeIndex = -1;
|
|
int tmpOppositeNodeIndex = -1;
|
|
if(isForward)
|
|
{
|
|
tmpLookupNodeIndex = currUIndex;
|
|
tmpOppositeNodeIndex = currWIndex;
|
|
}else{
|
|
tmpLookupNodeIndex = currWIndex;
|
|
tmpOppositeNodeIndex = currUIndex;
|
|
}
|
|
|
|
HlNodeEntry* currHlNodeEntry = nodesEdgesVector[tmpLookupNodeIndex];
|
|
|
|
//get data
|
|
std::vector<HlEdgeEntry*>* currEdgeVector =
|
|
currHlNodeEntry->getEdgesVector();
|
|
|
|
HlEdgeEntry* currEdge = hlGetEdgeFromVector(currEdgeVector,
|
|
tmpOppositeNodeIndex);
|
|
|
|
//shortcut parent
|
|
int currVIndex = -1;
|
|
|
|
//if is reverse edge we need to get the reverse-edges parent
|
|
if(isForward)
|
|
{
|
|
currVIndex = currEdge->getParentIndexForward();
|
|
}else{
|
|
currVIndex = currEdge->getParentIndexReverse();
|
|
}
|
|
|
|
//check if is shortcut, recursive call if true
|
|
if(currVIndex != -1)
|
|
{
|
|
bool isForwardShortcut = true;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("is shortcut, resolve (uIndex, vIndex): ("
|
|
<< currUIndex << ", " << currVIndex << ")" << endl);
|
|
#endif
|
|
|
|
//(u, v)
|
|
//the shortcuts part-edge u-> v always is to be searched
|
|
// as reverse edge because u and w mus have higher rank than v
|
|
//this is independent of whether we are currently iterating the
|
|
// forward or reverse vector
|
|
hlResolveShortcutAndAddToOrel(currUIndex, currVIndex,
|
|
nodesEdgesVector, resultEdgesRel, edgesSourceOrel,
|
|
!isForwardShortcut);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("is shortcut, resolve (vIndex, wIndex): ("
|
|
<< currVIndex << ", " << currWIndex << ")" << endl);
|
|
#endif
|
|
|
|
//(v, w)
|
|
//the shortcuts part-edge v-> w always is to be searched
|
|
// as forward edge because u and w mus have higher rank than v
|
|
//this is independent of whether we are currently iterating the
|
|
// forward or reverse vector
|
|
hlResolveShortcutAndAddToOrel(currVIndex, currWIndex,
|
|
nodesEdgesVector, resultEdgesRel, edgesSourceOrel,
|
|
isForwardShortcut);
|
|
}else{
|
|
#ifdef USEDEBUG
|
|
LogDebug("no shortcut, add to result relation (uIndex, wIndex): ("
|
|
<< currUIndex << ", " << currWIndex << ")" << endl);
|
|
#endif
|
|
//no shortcut so add it to resultrel
|
|
|
|
//get OSM nodeIds
|
|
HlNodeEntry* currUNodeEntry = nodesEdgesVector[currUIndex];
|
|
HlNodeEntry* currWNodeEntry = nodesEdgesVector[currWIndex];
|
|
int currUNodeId = currUNodeEntry->getNodeId();
|
|
int currWNodeId = currWNodeEntry->getNodeId();
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("osm Node IDs: (u, w): ("
|
|
<< currUNodeId << ", " << currWNodeId << ")" << endl);
|
|
#endif
|
|
|
|
//get osm-edge Tuple
|
|
CcInt* sourceNodeIdCcInt = new CcInt(true, currUNodeId);
|
|
CcInt* targetNodeIdCcInt = new CcInt(true, currWNodeId);
|
|
Tuple* currOrelTuple = hlGetEdgeFromOrel(edgesSourceOrel,
|
|
sourceNodeIdCcInt, targetNodeIdCcInt);
|
|
delete sourceNodeIdCcInt;
|
|
delete targetNodeIdCcInt;
|
|
|
|
//insert into result relTuple
|
|
resultEdgesRel->AppendTuple(currOrelTuple);
|
|
|
|
currOrelTuple->DeleteIfAllowed();
|
|
currOrelTuple = 0;
|
|
}
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlResolveShortcutAndAddToOrel" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Iterates through the given Edges-Orel from OSM Graph and
|
|
* retrieves the length of every curve.
|
|
* Also retrieves the RoadType of the specific edge and multiplies
|
|
* the length with a const valua representing the driving speed
|
|
* valid for this RoadType.
|
|
* Stores the calculated weights within the field Costs
|
|
* of the specific edge.
|
|
* Expects the Osm-Orel to fulfil the schema of
|
|
* @see hlGetEdgesTupleTypeInfo()
|
|
*
|
|
* Supports a parameter to give the calculation mode but currently
|
|
* it is not implemented.
|
|
*
|
|
* @param edgesOrelOsm the input Edges-Orel from OSM Import
|
|
* @param calcMode the calculation mode to use (not yet implemented)
|
|
* @param true since all modifications are done within the given parameters
|
|
*
|
|
*/
|
|
void hlCalcWeightsOrel(OrderedRelation* edgesOrel, int calcMode) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlCalcWeightsOrel" << endl);
|
|
#endif
|
|
|
|
GenericRelationIterator* edgesOrelIter = edgesOrel->MakeScan();
|
|
Tuple* currTuple = edgesOrelIter->GetNextTuple();
|
|
|
|
while(currTuple)
|
|
{
|
|
//for non static use
|
|
int indexCosts = HubLabelClass::HL_INDEX_OF_COSTS_IN_EDGE_TUPLE;
|
|
|
|
SimpleLine* curve = (SimpleLine*) currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_CURVE_IN_EDGE_TUPLE);
|
|
FText* roadTypeFText = (FText*) currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ROAD_TYPE_IN_EDGE_TUPLE);
|
|
|
|
//get data
|
|
double curveLength = curve->Length();
|
|
string roadType = roadTypeFText->GetValue();
|
|
|
|
int assumedSpeed = 0;
|
|
double calculatedCosts = 0.0;
|
|
|
|
//get speed information
|
|
int defaultSpeed = 30; //Default Speed for unkown cases
|
|
int motorwayLike = 130; //Autobahn
|
|
int motorwayLinkLike = 80; //Autobahn Auf- und Abfahrt
|
|
int trunkLike = 60; //Ausgebaute Schnellstraße
|
|
int trunkLinkLike = 110; //Auf-/ Abfahrt zu Schnellstraßen
|
|
int primaryLike = 90; //Bundesstraßen
|
|
int primaryLinkLike = 30; //Auf-/ Abfahrt zu Bundesstraßen
|
|
int secondaryLike = 70; //Landstraßen
|
|
int secondaryLinkLike = 30; //Auf-/ Abfahrt zu Landstraßen
|
|
int tertiaryLike = 70; //Kreisstraßen
|
|
int tertiaryLinkLike = 30; //Auf-/ Abfahrt zu Kreisstraßen
|
|
int roadLike = defaultSpeed;//Unknown type treat as slow
|
|
int residentialLike = 40; //Anwohnerstraßen
|
|
int livingStreetLike = 20; //Spielstraße
|
|
int unclassifiedLike = 40; //asphaltierte Feldwege
|
|
|
|
if(roadType == "motorway")
|
|
{
|
|
//Autobahn -> 130
|
|
assumedSpeed = motorwayLike;
|
|
}
|
|
else if(roadType == "motorway_link")
|
|
{
|
|
//Autobahn Auf- und Abfahrt -> 30
|
|
assumedSpeed = motorwayLinkLike;
|
|
}
|
|
else if(roadType == "trunk")
|
|
{
|
|
//Ausgebaute Schnellstraße -> 110
|
|
assumedSpeed = trunkLike;
|
|
}
|
|
else if(roadType == "trunk_link")
|
|
{
|
|
//Auf-/ Abfahrt zu Schnellstraßen -> 30
|
|
assumedSpeed = trunkLinkLike;
|
|
}
|
|
else if(roadType == "primary")
|
|
{
|
|
//Bundesstraßen -> 90
|
|
assumedSpeed = primaryLike;
|
|
}
|
|
else if(roadType == "primary_link")
|
|
{
|
|
//Auf-/ Abfahrt zu Bundesstraßen -> 30
|
|
assumedSpeed = primaryLinkLike;
|
|
}
|
|
else if(roadType == "secondary")
|
|
{
|
|
//Landstraßen -> 70
|
|
assumedSpeed = secondaryLike;
|
|
}
|
|
else if(roadType == "secondary_link")
|
|
{
|
|
//Auf-/ Abfahrt zu Landstraßen -> 30
|
|
assumedSpeed = secondaryLinkLike;
|
|
}
|
|
else if(roadType == "tertiary")
|
|
{
|
|
//Kreisstraßen -> 70
|
|
assumedSpeed = tertiaryLike;
|
|
}
|
|
else if(roadType == "tertiary_link")
|
|
{
|
|
//Auf-/ Abfahrt zu Kreisstraßen -> 30
|
|
assumedSpeed = tertiaryLinkLike;
|
|
}
|
|
else if(roadType == "road")
|
|
{
|
|
//Unknown type treat as slow -> 30
|
|
assumedSpeed = roadLike;
|
|
}
|
|
else if(roadType == "residential")
|
|
{
|
|
//Anwohnerstraßen -> 40
|
|
assumedSpeed = residentialLike;
|
|
}
|
|
else if(roadType == "living_street")
|
|
{
|
|
//Spielstraße -> 20
|
|
assumedSpeed = livingStreetLike;
|
|
}
|
|
else if(roadType == "unclassified")
|
|
{
|
|
//asphaltierte Feldwege -> 40
|
|
assumedSpeed = unclassifiedLike;
|
|
}
|
|
else
|
|
{
|
|
//Default Speed like unknown 'road'
|
|
assumedSpeed = defaultSpeed;
|
|
}
|
|
|
|
//calc
|
|
|
|
//curveLength = way in km
|
|
//speed given in km/h = way per time
|
|
//travel time = way / way per time
|
|
// -> curveLength / speed
|
|
//
|
|
// we think to multiply length by 10 to get the value with
|
|
// unit nearly to be kilometer (does not fit exactly like measuring
|
|
// with google, duffers about several ten meters
|
|
//
|
|
calculatedCosts = curveLength * 10 / assumedSpeed;
|
|
|
|
//set costs
|
|
CcReal* newCosts = new CcReal();
|
|
newCosts->Set(true, calculatedCosts);
|
|
|
|
//prepare updateTuple
|
|
std::vector<int> changedIndices;
|
|
changedIndices.push_back(indexCosts);
|
|
|
|
std::vector<Attribute*> changedAttributes;
|
|
changedAttributes.push_back(newCosts);
|
|
|
|
|
|
//update costs
|
|
edgesOrel->UpdateTuple(currTuple, changedIndices,
|
|
changedAttributes);
|
|
|
|
//Free Outgoing-Iteration
|
|
currTuple->DeleteIfAllowed();
|
|
currTuple = 0;
|
|
currTuple = edgesOrelIter->GetNextTuple();
|
|
}
|
|
|
|
//Free Iterator
|
|
delete edgesOrelIter;
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlCalcWeightsOrel" << endl);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Nimmt einen hlGraph entgegen und führt eine HL Search für jeden Knoten
|
|
* aus dem hlGraph aus und persistiert die resultierenden SearchTrees.
|
|
*
|
|
* TODO:die ursprünglich space efficient serchTree Struktur wird hier nicht
|
|
* wiederverwendet für die persistierung der Labels
|
|
* Statdessen wird die alte NRel darstellung aus dem
|
|
* ersten Versuch verwendet
|
|
*
|
|
* @param allLabelsNrel the nrel to persist labels to be cerated
|
|
* @param nodesOrel an orel containing all nodes of the hlGraph
|
|
* @param nodesEdgesVector by reference the hlGraph to fill
|
|
* @param true since all modifications are done within the given parameters
|
|
*
|
|
*/
|
|
void hlCreateLabelsFromHlGraph(NestedRelation* allLabelsNrel,
|
|
OrderedRelation* nodesOrel,
|
|
std::vector<HlNodeEntry*> nodesEdgesVector) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlCreateLabelsFromHlGraph" << endl);
|
|
#endif
|
|
|
|
#ifdef USEPERF
|
|
int totalLabelSizeForward = 0;
|
|
int totalLabelSizeReverse = 0;
|
|
#endif
|
|
|
|
|
|
bool isChElseHl = false;
|
|
|
|
//prepare nestedRelation
|
|
SubRelation* forwardDataSubRel =
|
|
allLabelsNrel->getSubRel(
|
|
hlForwardLabelColumnName());
|
|
SubRelation* reverseDataSubRel =
|
|
allLabelsNrel->getSubRel(
|
|
hlReverseLabelColumnName());
|
|
|
|
SmiFileId forwardDataSubRelFileId =
|
|
forwardDataSubRel->fileId;
|
|
SmiFileId reverseDataSubRelFileId =
|
|
reverseDataSubRel->fileId;
|
|
|
|
ListExpr forwardDataSubRelTypeInfo =
|
|
forwardDataSubRel->typeInfo;
|
|
ListExpr reverseDataSubRelTypeInfo =
|
|
reverseDataSubRel->typeInfo;
|
|
|
|
Relation* forwardDataRel = forwardDataSubRel->rel;
|
|
Relation* reverseDataRel = reverseDataSubRel->rel;
|
|
|
|
TupleType* tupleTypeAllLabels =
|
|
allLabelsNrel->getPrimary()->GetTupleType();
|
|
|
|
//iterate through nodesOrel and create Labels for every Node
|
|
GenericRelationIterator* nodesOrelIter = nodesOrel->MakeScan();
|
|
|
|
//Get first Tuple
|
|
Tuple* currNode = nodesOrelIter->GetNextTuple();
|
|
|
|
#ifdef USEINFO
|
|
int nodesCount = nodesOrel->GetNoTuples();
|
|
int progressCount = 0;
|
|
#endif
|
|
|
|
|
|
//Iterate over all Tuples
|
|
while(currNode)
|
|
{
|
|
CcInt* currNodeIdCcInt = (CcInt*) currNode->GetAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_HL_GRAPH_NODES);
|
|
|
|
int currNodeId = currNodeIdCcInt->GetIntval();
|
|
|
|
#ifdef USEINFO
|
|
++progressCount;
|
|
if(progressCount % getProgressInterval() == 0)
|
|
{
|
|
LogInfo("Create Labels for next nodeId: "
|
|
<< currNodeId << " (progress: " << progressCount
|
|
<< " nodes left: " << (nodesCount - progressCount) << ")"
|
|
<< endl);
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("forward and reverse label multimaps" << endl);
|
|
#endif
|
|
std::multimap<int, std::tuple<int, int, double>>
|
|
labelForwardMultimap;
|
|
std::multimap<int, std::tuple<int, int, double>>
|
|
labelReverseMultimap;
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("do search" << endl);
|
|
#endif
|
|
std::tuple<int, double, std::map<int, ChNode*>> searchResultTuple =
|
|
hlDoCHSearch(nodesEdgesVector, currNodeId, currNodeId, isChElseHl);
|
|
|
|
std::map<int, ChNode*> searchTree = std::get<2>(searchResultTuple);
|
|
|
|
|
|
//iterate through searchTree
|
|
for (std::map<int, ChNode*>::iterator
|
|
searchTreeIter = searchTree.begin();
|
|
searchTreeIter != searchTree.end();
|
|
++searchTreeIter)
|
|
{
|
|
|
|
int currHubIndex = (*searchTreeIter).first;
|
|
ChNode* currHubChNode = (*searchTreeIter).second;
|
|
|
|
double distForward = currHubChNode->getDistForward();
|
|
double distReverse = currHubChNode->getDistReverse();
|
|
int predecessorIndexForward =
|
|
currHubChNode->getPredecessorIndexForward();
|
|
int predecessorIndexReverse =
|
|
currHubChNode->getPredecessorIndexReverse();
|
|
|
|
delete currHubChNode;
|
|
|
|
|
|
HlNodeEntry* currHubNodeEntry = nodesEdgesVector[currHubIndex];
|
|
int currHubNodeId = currHubNodeEntry->getNodeId();
|
|
int currHubRankValue = currHubNodeEntry->getRankValue();
|
|
|
|
//only get predecessor if there is one
|
|
// it can be -1 or -2
|
|
int currPredecessorForwardNodeId = -1;
|
|
if(predecessorIndexForward > -1)
|
|
{
|
|
HlNodeEntry* currPredecessorForwardNodeEntry =
|
|
nodesEdgesVector[predecessorIndexForward];
|
|
currPredecessorForwardNodeId =
|
|
currPredecessorForwardNodeEntry->getNodeId();
|
|
}
|
|
|
|
int currPredecessorReverseNodeId = -1;
|
|
if(predecessorIndexReverse > -1)
|
|
{
|
|
HlNodeEntry* currPredecessorReverseNodeEntry =
|
|
nodesEdgesVector[predecessorIndexReverse];
|
|
currPredecessorReverseNodeId =
|
|
currPredecessorReverseNodeEntry->getNodeId();
|
|
}
|
|
|
|
|
|
|
|
|
|
//add to forward label if is sourceNode or if is hub
|
|
// which always has a forward predecessor
|
|
if(currNodeId == currHubNodeId ||
|
|
predecessorIndexForward > -1)
|
|
{
|
|
|
|
//rankOfHub/nodeIdNew, hubNodeId, predecessorId,
|
|
// distToSource
|
|
labelForwardMultimap.insert(std::make_pair(currHubRankValue,
|
|
std::make_tuple(currHubNodeId,
|
|
currPredecessorForwardNodeId, distForward)));
|
|
}
|
|
|
|
//add to reverse label if is sourceNode or if is hub
|
|
// which always has a reverse predecessor
|
|
if(currNodeId == currHubNodeId ||
|
|
predecessorIndexReverse > -1)
|
|
{
|
|
|
|
//rankOfHub/nodeIdNew, hubNodeId, predecessorId,
|
|
// distToSource
|
|
labelReverseMultimap.insert(std::make_pair(currHubRankValue,
|
|
std::make_tuple(currHubNodeId,
|
|
currPredecessorReverseNodeId, distReverse)));
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("prepare NestedRelationTuple" << endl);
|
|
#endif
|
|
|
|
Tuple* allLabelsTuple = new Tuple(
|
|
tupleTypeAllLabels);
|
|
allLabelsTuple->PutAttribute(
|
|
HL_INDEX_OF_NODE_ID_IN_ALL_LABELS_TUPLE,
|
|
new CcInt(true, currNodeId));
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("create and fill forwardLabel" << endl);
|
|
#endif
|
|
AttributeRelation* labelForwardArel = new
|
|
AttributeRelation(forwardDataSubRelFileId,
|
|
forwardDataSubRelTypeInfo,
|
|
labelForwardMultimap.size());
|
|
labelForwardArel->setPartOfNrel(true);
|
|
|
|
hlFillForwardOrReverseLabel(labelForwardArel, forwardDataRel,
|
|
labelForwardMultimap);
|
|
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("add forward label to all labels" << endl);
|
|
#endif
|
|
allLabelsTuple->PutAttribute(
|
|
HL_INDEX_OF_FORWARD_LABEL_IN_ALL_LABELS_TUPLE,
|
|
labelForwardArel);
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("create and fill reverseLabel" << endl);
|
|
#endif
|
|
AttributeRelation* labelReverseArel = new
|
|
AttributeRelation(reverseDataSubRelFileId,
|
|
reverseDataSubRelTypeInfo,
|
|
labelReverseMultimap.size());
|
|
labelReverseArel->setPartOfNrel(true);
|
|
|
|
hlFillForwardOrReverseLabel(labelReverseArel, reverseDataRel,
|
|
labelReverseMultimap);
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("add reverse label to all labels" << endl);
|
|
#endif
|
|
allLabelsTuple->PutAttribute(
|
|
HL_INDEX_OF_REVERSE_LABEL_IN_ALL_LABELS_TUPLE,
|
|
labelReverseArel);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish current all labels Tuple" << endl);
|
|
#endif
|
|
|
|
#ifdef USEPERF
|
|
totalLabelSizeForward += labelForwardMultimap.size();
|
|
totalLabelSizeReverse += labelReverseMultimap.size();
|
|
#endif
|
|
|
|
allLabelsNrel->getPrimary()->AppendTuple(
|
|
allLabelsTuple);
|
|
|
|
allLabelsTuple->DeleteIfAllowed();
|
|
allLabelsTuple = 0;
|
|
|
|
|
|
//get next Tuple from Orel
|
|
currNode->DeleteIfAllowed();
|
|
currNode = 0;
|
|
currNode = nodesOrelIter->GetNextTuple();
|
|
}
|
|
|
|
delete nodesOrelIter;
|
|
|
|
|
|
|
|
#ifdef USEPERF
|
|
LogPerf("perf: total labelSizeForward: " << totalLabelSizeForward
|
|
<< " totalLabelSizeReverse: " << totalLabelSizeReverse
|
|
<< " nodesCount: " << nodesCount << " average labelSizeForward: "
|
|
<< totalLabelSizeForward / nodesCount << " average labelSizeReverse: "
|
|
<< totalLabelSizeReverse / nodesCount << " average labelSizeBoth: "
|
|
<< (totalLabelSizeForward + totalLabelSizeReverse) / (nodesCount * 2)
|
|
<< endl);
|
|
#endif
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlCreateLabelsFromHlGraph" << endl);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
3.4 HubLabeling functionality of (3) In-Memory Approach using MainMemory2Algebra
|
|
|
|
*/
|
|
/*
|
|
* TODO: function for doing ContractionHierarchies
|
|
* using graph from existing Algebra MainMemory2
|
|
* and its shortestPath implementations
|
|
* Not working yet.
|
|
*/
|
|
bool hlContractMmGraph(graph::Graph* graphUp, graph::Graph* graphDown,
|
|
Word calcFunction) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlContractMmGraph" << endl);
|
|
#endif
|
|
|
|
graph::Queue rankQueue;
|
|
|
|
//it doesnt matter here which graph to use, both have the same nodes
|
|
set<graph::Vertex*,graph::Vertex::EqualVertex>::iterator vertexIt =
|
|
graphUp->getGraph()->begin();
|
|
//iterate over all nodes
|
|
int currRank = 1;
|
|
std::multimap<int, int> ranksNodesMultimap;
|
|
while(vertexIt != graphUp->getGraph()->end()) {
|
|
graph::Vertex* v = *vertexIt;
|
|
|
|
ranksNodesMultimap.insert(pair<int, int>(currRank, v->getNr()));
|
|
|
|
vertexIt++;
|
|
currRank++;
|
|
}
|
|
|
|
//iterate over all nodes v in ranked order
|
|
while(!ranksNodesMultimap.empty())
|
|
{
|
|
//get first element of multimap
|
|
std::multimap<int,int>::iterator rankIter =
|
|
ranksNodesMultimap.begin();
|
|
|
|
//int rankV = (*rankIter).first;
|
|
int vId = (*rankIter).second;
|
|
|
|
//remove node from multimap its not used any more
|
|
ranksNodesMultimap.erase(rankIter);
|
|
|
|
//get incoming edges (u, v) to v
|
|
graph::Vertex* vDown = graphDown->getVertex(vId);
|
|
for(size_t iDown = 0; iDown < vDown->getEdges()->size(); iDown++)
|
|
{
|
|
//get u from ! graphUp for doing forward searches
|
|
// but reach u via ! downGraph
|
|
vector<graph::EdgeWrap>* edgesDown = vDown->getEdges();
|
|
int uId = edgesDown->at(iDown).getPointer()->getDest();
|
|
graph::Vertex* uUp = graphUp->getVertex(uId);
|
|
|
|
//skip if u does not exist in rankMultimap
|
|
// it then still must have been contracted
|
|
// we use function to get the nodes rank
|
|
// which is -1 if the node does not exist
|
|
int rankU = hlGetRankOfNode(ranksNodesMultimap, uId);
|
|
if(rankU > -1)
|
|
{
|
|
graph::Vertex* vUp = graphUp->getVertex(vId);
|
|
for(size_t iUp = 0; iUp < vUp->getEdges()->size(); iUp++)
|
|
{
|
|
//get w from ! downGraph for doing reverse searches
|
|
// but reach w via ! UpGraph
|
|
vector<graph::EdgeWrap>* edgesUp = vUp->getEdges();
|
|
int wId = edgesUp->at(iUp).getPointer()->getDest();
|
|
//graph::Vertex* wDown = graphDown->getVertex(wId);
|
|
|
|
//skip if w does not exist in rankMultimap
|
|
// it then still must have been contracted
|
|
// we use function to get the nodes rank
|
|
// which is -1 if the node does not exist
|
|
int rankW = hlGetRankOfNode(ranksNodesMultimap, wId);
|
|
if(rankW > -1)
|
|
{
|
|
graph::Vertex* wUp = graphUp->getVertex(wId);
|
|
|
|
//do local query from u to w
|
|
//TODO wie dijkstra aufrufen von hier aus?
|
|
bool dijkstraFound = mm2algebra::dijkstra(graphUp,
|
|
calcFunction, uUp, wUp);
|
|
|
|
if(!dijkstraFound)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("no shortest path found" << endl);
|
|
#endif
|
|
}
|
|
|
|
//retrieve distance of previous local query
|
|
double distUW = wUp->getCost();
|
|
|
|
//calc shortcutLength for UV
|
|
//note that down is the same as up but only
|
|
// with invertes edges, means
|
|
// dist(u, v) \in up = dist(v, u) \in down
|
|
double distUV = hlGetCostOfEdgeUV(
|
|
vDown, iDown, calcFunction);
|
|
|
|
//calc shortcutLength for UV
|
|
double distVW = hlGetCostOfEdgeUV(
|
|
vUp, iUp, calcFunction);
|
|
|
|
double distUVWShortcut = distUV + distVW;
|
|
|
|
//if shortcut is shorter then create shortcu-edge
|
|
if(distUVWShortcut < distUW)
|
|
{
|
|
//add edge (u, w) to up
|
|
// and inverted edge (w, u) to down
|
|
hlCreateShortcutEdgeTuple(graphUp, uId, wId,
|
|
distUVWShortcut, vId);
|
|
hlCreateShortcutEdgeTuple(graphDown, wId, uId,
|
|
distUVWShortcut, vId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlContractMmGraph" << endl);
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* retrieves the costs of an edge (u, v) of an graph:Graph
|
|
*
|
|
* @param vertexU is the given graph::Vertex* u
|
|
* @param vIndex is the index position of the edge which leads to vertex v
|
|
* @param calcFunction is the Function used to calculate the cost
|
|
*
|
|
* @return the calculated costs of the given edge
|
|
*/
|
|
double hlGetCostOfEdgeUV(graph::Vertex* vertexU, int vIndex,
|
|
Word calcFunction) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlGetCostOfEdgeUV" << endl);
|
|
#endif
|
|
//TODO: costFunction auf festes Feld umbauen,
|
|
// damit Shortcutsunterstützt werden können?
|
|
// ansonsten müsste für diese ja auch die curve definiert werden
|
|
|
|
double cost = -1.0;
|
|
|
|
ArgVectorPointer funArgs = qp->Argument(calcFunction.addr);
|
|
Word funResult;
|
|
((*funArgs)[0]).setAddr(
|
|
vertexU->getEdges()->at(vIndex).getPointer()->getTuple()
|
|
);
|
|
qp->Request(calcFunction.addr,funResult);
|
|
cost = ((CcReal*)funResult.addr)->GetRealval();
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlGetCostOfEdgeUV" << endl);
|
|
#endif
|
|
|
|
return cost;
|
|
}
|
|
|
|
/*
|
|
* Retrieves the Rank for the given nodeId
|
|
*
|
|
* @param currMultimap the map containing all nodes with their ranks
|
|
* ordered by nodeId
|
|
* @param nodeId
|
|
* @return the rank if found, -1 telse
|
|
*/
|
|
int hlGetRankOfNode(std::multimap<int, int> currMultimap,
|
|
int nodeId) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlGetRankOfNode" << endl);
|
|
#endif
|
|
|
|
int rankValue = -1;
|
|
std::multimap<int,int>::iterator multimapIter =
|
|
currMultimap.find(nodeId);
|
|
|
|
if(multimapIter != currMultimap.end())
|
|
{
|
|
rankValue = (*multimapIter).second;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlGetRankOfNode" << endl);
|
|
#endif
|
|
|
|
return rankValue;
|
|
}
|
|
|
|
/*
|
|
* Creates an Shortcut Tuple (u, v, w) and adds it to the given graph
|
|
* Uses @see HubLabelClass::hlGetEdgesTupleTypeInfo()
|
|
*
|
|
* @param graph where the edge shall be added
|
|
* @param source the index of the Attribute containing the sourceId u
|
|
* @param target the index of the Attribute containing the targetId w
|
|
* @param costs the costs of the shortcutEdge to be created
|
|
* @param parentNode the nodeId of the parent v
|
|
*
|
|
*/
|
|
void hlCreateShortcutEdgeTuple(graph::Graph* graph, int source,
|
|
int target, double costs, int parentNode) const
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlCreateShortcutEdgeTuple" << endl);
|
|
#endif
|
|
|
|
ListExpr tupleType;
|
|
nl->ReadFromString(HubLabelClass::hlGetEdgesTupleTypeInfo(), tupleType);
|
|
ListExpr tupNumType =
|
|
SecondoSystem::GetCatalog()->NumericType(tupleType);
|
|
Tuple* insertTuple = new Tuple(tupNumType);
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE, new CcInt(true, source));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE, new CcInt(true, target));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_SOURCE_POS_IN_EDGE_TUPLE,
|
|
new Point(false, 0.0, 0.0));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_TARGET_POS_IN_EDGE_TUPLE,
|
|
new Point(false, 0.0, 0.0));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_SOURCE_NODE_COUNTER_IN_EDGE_TUPLE,
|
|
new CcInt(false));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_TARGET_NODE_COUNTER_IN_EDGE_TUPLE,
|
|
new CcInt(false));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_CURVE_IN_EDGE_TUPLE,
|
|
new SimpleLine(0));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_ROAD_NAME_IN_EDGE_TUPLE,
|
|
new FText(false));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_ROAD_TYPE_IN_EDGE_TUPLE,
|
|
new FText(false));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_WAY_ID_IN_EDGE_TUPLE,
|
|
new LongInt(false));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_COSTS_IN_EDGE_TUPLE, new CcReal(true, costs));
|
|
insertTuple->PutAttribute(
|
|
HL_INDEX_OF_PARENT_ID_IN_EDGE_TUPLE,
|
|
new CcInt(true, parentNode));
|
|
|
|
//TODO sinnvoll, dass hier cost gesetzt wird?
|
|
// oder ist das nur relevant für die dijkstrasuche?
|
|
graph->addEdge(insertTuple,
|
|
HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE,
|
|
HL_INDEX_OF_TARGET_IN_EDGE_TUPLE,
|
|
costs, 0.0);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlCreateShortcutEdgeTuple" << endl);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
double x;
|
|
double y;
|
|
double r;
|
|
|
|
int progressInterval;
|
|
};
|
|
|
|
|
|
/*
|
|
4 HubLabeling Secondo-Type
|
|
|
|
In the following sections show the implementation of
|
|
the HubLabeling Secondo-Type
|
|
related to the class HubLabelClass above.
|
|
|
|
4.1 The Property Function
|
|
|
|
The ~Property~ function provides a description of the Secondo type
|
|
to the user. It returns a nested list, which must be have exactly
|
|
the format given in this example. The first element of the list
|
|
is always the same and the second element of the list contains
|
|
type specific descriptions.
|
|
|
|
*/
|
|
|
|
ListExpr HubLabelClassProperty()
|
|
{
|
|
return ( nl->TwoElemList (
|
|
nl->FourElemList (
|
|
nl->StringAtom("Signature"),
|
|
nl->StringAtom("Example Type List"),
|
|
nl->StringAtom("List Rep"),
|
|
nl->StringAtom("Example List")),
|
|
nl->FourElemList (
|
|
nl->StringAtom("-> SIMPLE"),
|
|
nl->StringAtom(HubLabelClass::BasicType()),
|
|
nl->StringAtom("(real real real) = (x,y,r)"),
|
|
nl->StringAtom("(13.5 -76.0 1.0)")
|
|
)));
|
|
}
|
|
|
|
/*
|
|
4.2 In Function
|
|
|
|
For the creation of a constant value within a query and for
|
|
importing objects or whole databases from a file, object
|
|
values are described by nested lists. The task of the ~IN~-function
|
|
is to convert such a list into the internal object representation, i.e.
|
|
into an instance of the class above.
|
|
The list may have an invalid format. If the list does not
|
|
have the expected format, the output parameter ~correct~ must be set to
|
|
~false~ and the ~addr~-pointer of the result must be set to 0.
|
|
A detailed error description can be provided to the user by calling
|
|
the ~inFunError~ of the global ~cmsg~ object.
|
|
In case of success, the argument ~correct~ has to be set to ~true~ and
|
|
the ~addr~ pointer of the result points to an object instance having the
|
|
value represented by the ~instance~ argument.
|
|
The parameters of the function are:
|
|
|
|
* ~typeInfo~: contains the complete type description and is required
|
|
for nested types
|
|
like tuples
|
|
|
|
* ~instance~: the value of the object in external (nested list) representation
|
|
|
|
* ~errorPos~: output parameter reporting the position of an error within
|
|
the list (set types)
|
|
|
|
* ~errorInfo~: can provide information about an error to the user
|
|
|
|
* ~correct~: output parameter returning the success of this call
|
|
|
|
|
|
|
|
*/
|
|
|
|
Word InHubLabelClass( const ListExpr typeInfo,
|
|
const ListExpr instance,
|
|
const int errorPos, ListExpr& errorInfo,
|
|
bool& correct )
|
|
{
|
|
// create a result with addr pointing to 0
|
|
Word res((void*)0);
|
|
// assume an incorrect list
|
|
correct = false;
|
|
// check whether the list has three elements
|
|
if(!nl->HasLength(instance,3))
|
|
{
|
|
cmsg.inFunError("expected three numbers");
|
|
return res;
|
|
}
|
|
// check whether all elements are numeric
|
|
if( !listutils::isNumeric(nl->First(instance))
|
|
|| !listutils::isNumeric(nl->Second(instance))
|
|
|| !listutils::isNumeric(nl->Third(instance)))
|
|
{
|
|
cmsg.inFunError("expected three numbers");
|
|
return res;
|
|
}
|
|
// get the numeric values of the elements
|
|
double x = listutils::getNumValue(nl->First(
|
|
instance));
|
|
double y = listutils::getNumValue(nl->Second(
|
|
instance));
|
|
double r = listutils::getNumValue(nl->Third(
|
|
instance));
|
|
// check for a valid radius
|
|
if(r<=0)
|
|
{
|
|
cmsg.inFunError("invalid radius (<=0)");
|
|
return res;
|
|
}
|
|
// list was correct, create the result
|
|
correct = true;
|
|
res.addr = new HubLabelClass(x,y,r);
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
4.3 Out Function
|
|
|
|
This function is used to create the external representation of an object
|
|
as nested list. Note that the ~IN~ function must be able to read in the
|
|
result of this function. The arguments are:
|
|
|
|
* ~typeInfo~: nested list representing the type of the object (required for
|
|
complex types)
|
|
|
|
* ~value~: the ~addr~ pointer of ~value~ points to the object to export.
|
|
The Secondo
|
|
framework ensures that the type of this object is the correct one. The
|
|
cast in the first line will be successful.
|
|
|
|
|
|
This function must be able to convert *each* instance into a nested list.
|
|
For this
|
|
reason, there is no function for error reporting as in the ~IN~ function.
|
|
|
|
|
|
*/
|
|
ListExpr OutHubLabelClass( ListExpr typeInfo,
|
|
Word value )
|
|
{
|
|
HubLabelClass* k = (HubLabelClass*) value.addr;
|
|
return nl->ThreeElemList(
|
|
nl->RealAtom(k->getX()),
|
|
nl->RealAtom(k->getY()),
|
|
nl->RealAtom(k->getR()));
|
|
}
|
|
|
|
/*
|
|
4.4 Create Function
|
|
|
|
This function creates an object instance having an arbitrary value.
|
|
The ~typeInfo~
|
|
argument represents the type of the object and is required for nested types like
|
|
tuples.
|
|
|
|
*/
|
|
Word CreateHubLabelClass( const ListExpr
|
|
typeInfo )
|
|
{
|
|
Word w;
|
|
w.addr = (new HubLabelClass(0,0,1.0));
|
|
return w;
|
|
}
|
|
|
|
/*
|
|
2.4 Delete Function
|
|
|
|
Removes the complete object (inclusive disc parts if there are any, see section
|
|
\ref{largeStructures}).
|
|
The Secondo framework ensures that the type behind the ~addr~ pointer
|
|
of ~w~ is the expected one. The arguments are:
|
|
|
|
* ~typeInfo~: the type description (for complex types)
|
|
|
|
* ~w~: the ~addr~ pointer of this argument points to the object to delete.
|
|
|
|
*/
|
|
void DeleteHubLabelClass( const ListExpr typeInfo,
|
|
Word& w )
|
|
{
|
|
HubLabelClass *k = (HubLabelClass *)w.addr;
|
|
delete k;
|
|
w.addr = 0;
|
|
}
|
|
|
|
/*
|
|
4.5 Open Function
|
|
|
|
Reads an object from disc via an ~SmiRecord~.
|
|
|
|
* ~valueRecord~: here, the disc representation of the object is stored
|
|
|
|
* ~offset~: the object representation starts here in ~valueRecord~ After
|
|
the call of this function, ~offset~ must be after the object's value
|
|
|
|
* ~typeInfo~: the type description (required for complex types)
|
|
|
|
* ~value~: output argument
|
|
|
|
The function reads data out of the SmiRecord and creates a new object from them
|
|
in case of success. The created object is stored in the ~addr~-pointer of the
|
|
~value~ argument. In the case of an error, the ~addr~ pointer has to be set to
|
|
~NULL~. The result of this functions reports the success of reading.
|
|
To implement this function, the function ~Read~ of the ~SmiRecord~ is used.
|
|
Its first argument is a pointer to the storage where the data should be
|
|
written. The second argument determines how may data should be transferred
|
|
from the record to the buffer. The last argument indicates the position
|
|
of the data within the record. The return value of this function corresponds
|
|
to the actual read amount of data. In case of success, this number is
|
|
the same as given in the second argument.
|
|
|
|
*/
|
|
bool OpenHubLabelClass( SmiRecord& valueRecord,
|
|
size_t& offset, const ListExpr typeInfo,
|
|
Word& value )
|
|
{
|
|
size_t size = sizeof(double);
|
|
double x,y,r;
|
|
bool ok = (valueRecord.Read(&x,size,
|
|
offset) == size);
|
|
offset += size;
|
|
ok = ok &&
|
|
(valueRecord.Read(&y,size,offset) == size);
|
|
offset += size;
|
|
ok = ok &&
|
|
(valueRecord.Read(&r, size, offset) == size);
|
|
offset += size;
|
|
if(ok)
|
|
{
|
|
value.addr = new HubLabelClass(x,y,r);
|
|
}
|
|
else
|
|
{
|
|
value.addr = 0;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
/*
|
|
4.6 Save Function
|
|
|
|
Saves an object to disc (via SmiRecord). This function has to be symmetrically
|
|
to the ~OPEN~ function. The result reports the success of the call.
|
|
The arguments are
|
|
|
|
* ~valueRecord~: here the object will be stored
|
|
|
|
* ~offset~: the object has to be stored at this position in ~valueRecord~;
|
|
after the call of this
|
|
function, ~offset~ must be after the object's representation
|
|
|
|
* ~typeInfo~: type description as a nested list (required for complex types)
|
|
|
|
* ~value~: the addr pointer of this argument points to the object to save
|
|
|
|
The used ~Write~ function of the ~SmiRecord~ works similar to its ~Read~
|
|
function but transfers the
|
|
data into the other direction.
|
|
|
|
*/
|
|
|
|
bool SaveHubLabelClass( SmiRecord& valueRecord,
|
|
size_t& offset,
|
|
const ListExpr typeInfo, Word& value )
|
|
{
|
|
HubLabelClass* k = static_cast<HubLabelClass*>
|
|
( value.addr );
|
|
size_t size = sizeof(double);
|
|
double v = k->getX();
|
|
bool ok = valueRecord.Write( &v, size, offset );
|
|
offset += size;
|
|
v = k->getY();
|
|
ok = ok && valueRecord.Write(&v,size,offset);
|
|
offset += size;
|
|
v = k->getR();
|
|
ok = ok && valueRecord.Write(&v,size,offset);
|
|
offset += size;
|
|
return ok;
|
|
}
|
|
|
|
/*
|
|
4.7 Close Function
|
|
|
|
Removes the main memory part of an object. In contrast to delete, the
|
|
disc part of the object is untouched (if there is one).
|
|
|
|
* ~typeInfo~: type description as a nested list
|
|
|
|
* ~w~: the ~addr~ pointer of ~w~ points to the object which is to close
|
|
|
|
*/
|
|
void CloseHubLabelClass( const ListExpr typeInfo,
|
|
Word& w )
|
|
{
|
|
HubLabelClass *k = (HubLabelClass *)w.addr;
|
|
delete k;
|
|
w.addr = 0;
|
|
}
|
|
|
|
/*
|
|
4.8 Clone Function
|
|
|
|
Creates a depth copy (inclusive disc parts) of an object.
|
|
|
|
* ~typeInfo~: type description as nested list
|
|
|
|
* ~w~: holds a pointer to the object which is to clone
|
|
|
|
*/
|
|
Word CloneHubLabelClass( const ListExpr typeInfo,
|
|
const Word& w )
|
|
{
|
|
HubLabelClass* k = (HubLabelClass*) w.addr;
|
|
Word res;
|
|
res.addr = new HubLabelClass(k->getX(), k->getY(),
|
|
k->getR());
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
4.9 Cast Function
|
|
|
|
Casts a void pointer to the type using a special call of new operator.
|
|
The argument points to a memory block which is to cast to the object.
|
|
The used C++ constructor cannot initialize the object, e.g. the used
|
|
constructur must do nothing.
|
|
|
|
*/
|
|
void* CastHubLabelClass( void* addr )
|
|
{
|
|
return (new (addr) HubLabelClass);
|
|
}
|
|
|
|
/*
|
|
4.10 Type Check
|
|
|
|
Checks whether a given list corresponds to the type. This function
|
|
is quit similar to the ~checkType~ function within the class.
|
|
The result is ~true~ if ~type~ represents a valid type description for
|
|
the type, ~false~ otherwise. The argument ~errorInfo~ can be used
|
|
to report an error message to the user.
|
|
|
|
*/
|
|
bool HubLabelClassTypeCheck(ListExpr type,
|
|
ListExpr& errorInfo)
|
|
{
|
|
return nl->IsEqual(type,
|
|
HubLabelClass::BasicType());
|
|
}
|
|
|
|
/*
|
|
4.11 SizeOf Function
|
|
|
|
Returns the size required to store an instance of this object to disc
|
|
using the ~Save~ function from above. Because an ~HubLabelClass~ is represented
|
|
by three double numbers, the size is three times the size of a single double.
|
|
|
|
*/
|
|
int SizeOfHubLabelClass()
|
|
{
|
|
return 3*sizeof(double);
|
|
}
|
|
|
|
/*
|
|
4.12 The TypeConstructor Instance
|
|
|
|
We define a Secondo type by creating an instance of ~TypeConstructor~
|
|
feeded with
|
|
the functions defined before.
|
|
|
|
*/
|
|
|
|
TypeConstructor HubLabelClassTC(
|
|
HubLabelClass::BasicType(), // name of the type
|
|
HubLabelClassProperty, // property function
|
|
OutHubLabelClass,
|
|
InHubLabelClass, // out and in function
|
|
0, 0, // deprecated, don't think about it
|
|
CreateHubLabelClass,
|
|
DeleteHubLabelClass, // creation and deletion
|
|
OpenHubLabelClass,
|
|
SaveHubLabelClass, // open and save functions
|
|
CloseHubLabelClass,
|
|
CloneHubLabelClass, // close and clone functions
|
|
CastHubLabelClass, // cast function
|
|
SizeOfHubLabelClass, // sizeOf function
|
|
HubLabelClassTypeCheck); // type checking function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
5 Operator Implementation
|
|
|
|
The following sections show the implementation of the HubLabeling
|
|
Secondo-Operatoprrs
|
|
used to perform the functionalities of the class HubLabelClass.
|
|
Most of the operators are used mainly for testing the functionality.
|
|
|
|
Main-Use-Cases and the equivalent operators are:
|
|
-A given Graph can be modified with auxiliary attributes
|
|
- hlCalcRankOp
|
|
-The graph can be contracted
|
|
- hlIterateOverAllNodesByRankAscAndDoContractionOp
|
|
-The graph can be divided into upwards- and downwards graphs
|
|
-HubLabels can be created
|
|
- hlCreateLabels
|
|
-A HubLabeling Search can be performed
|
|
- hlQuery
|
|
For all steps the the equivalent Secondo-Script for full execution
|
|
of creating HubLabeling Labels
|
|
|
|
|
|
Each operator implementation in Secondo contains of a type mapping,
|
|
a set of value mappings, a selection function,
|
|
a description, and a creation of an operator instance.
|
|
|
|
Furthermore, the syntax of the operator is described in the file
|
|
~HubLabeling.spec~ and at least one example must be given in the file
|
|
~HubLabeling.examples~. If there is no example, the operator will be
|
|
switched off by the Secondo framework.
|
|
|
|
|
|
The following sections present the implementation ~HubLabelClass~.
|
|
|
|
5.1 Type Mapping
|
|
|
|
The type mapping gets a nested list containing the argument types
|
|
for this operator. Within the implementation, the number and the
|
|
types of the arguments are checked to be a valid input for the
|
|
operator. If the argument types cannot be handled by this operator,
|
|
a type error is returned. Otherwise, the result of this function
|
|
is the result type of the operator in nested list format.
|
|
|
|
All TypeMappings are related to the equal named function of the
|
|
class HubLabelClass.
|
|
The TypeMapping just got an additional suffix 'TM'.
|
|
|
|
5.1.1 Type Mappings of (1) Persistent Approach
|
|
|
|
*/
|
|
|
|
|
|
ListExpr hlCalcRankTM(ListExpr args)
|
|
{
|
|
string err =
|
|
"2x orderedRelation and one CcInt expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,3))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no CcInt)");
|
|
}
|
|
|
|
// return the result type
|
|
return listutils::basicSymbol<CcReal>();
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlOneHopReverseSearchTM(ListExpr args)
|
|
{
|
|
string err =
|
|
"2x orderedRelation and one CcInt expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,3))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no CcInt)");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetOneHopReverseOrelIdTypeInfo(),
|
|
relType);
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlHHopForwardSearchTM(ListExpr args)
|
|
{
|
|
string err =
|
|
"3x orderedRelation and 2x CcInt expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,5))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
if(!OrderedRelation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no OrderedRelation)");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no CcInt)");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no CcInt)");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetShortcutsCreatedSourceTypeInfo(),
|
|
relType);
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlForwardSearchGetDistTM(ListExpr args)
|
|
{
|
|
string err =
|
|
"1x orderedRelation and 2x CcInt expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,3))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no CcInt)");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no CcInt)");
|
|
}
|
|
|
|
// return the result type
|
|
return listutils::basicSymbol<CcReal>();
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlRemoveTFromCurrentWitnessListTM(
|
|
ListExpr args)
|
|
{
|
|
string err = "1x Orel and 1x CcInt expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,2))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no Orel)");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no CcInt");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetOneHopReverseOrelIdTypeInfo(),
|
|
relType);
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlForwardSearchCheckForWitnessPathTM(
|
|
ListExpr args)
|
|
{
|
|
string err =
|
|
"1x Orel, 2x CcInt, 2x CcReal expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,5))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no Orel)");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no CcInt");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no CcInt");
|
|
}
|
|
|
|
if(!CcReal::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no CcReal");
|
|
}
|
|
|
|
if(!CcReal::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no CcReal");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetOneHopReverseOrelIdTypeInfo(),
|
|
relType);
|
|
//TODO: warum hier kein numtype, im code aber schon?
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlInsertOrUpdateTupleInNotYetVisitedListTM(
|
|
ListExpr args)
|
|
{
|
|
string err = "1x rel, 3x CcInt expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,4))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!Relation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no rel)");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no CcInt");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no CcInt");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no CcInt");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetNotYetVisitedNodesTypeInfo(),
|
|
relType);
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlForwardSearchIterativeStepsScanNewVerticesTM(
|
|
ListExpr args)
|
|
{
|
|
string err =
|
|
"4x Orel, 1x Rel, 1 CcInt, 1x CcReal expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,7))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no orel)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no orel)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no orel)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no orel)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!Relation::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no rel)");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Sixth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (sixth arg no CcInt");
|
|
}
|
|
|
|
if(!CcReal::checkType(nl->Seventh(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (seventh arg no CcReal");
|
|
}
|
|
|
|
// return the result type
|
|
return listutils::basicSymbol<CcInt>();
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlForwardSearchProcessIncomingEdgeIterativeStepsTM(
|
|
ListExpr args)
|
|
{
|
|
string err =
|
|
"4x Orel, 2x CcInt, 1x CcReal expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,7))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no orel)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no orel)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no orel)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no orel)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no CcInt)");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Sixth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (sixth arg no CcInt");
|
|
}
|
|
|
|
if(!CcReal::checkType(nl->Seventh(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (seventh arg no CcReal");
|
|
}
|
|
|
|
// return the result type
|
|
return listutils::basicSymbol<CcInt>();
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlForwardSearchProcessIncomingEdgeInitialStepsTM(
|
|
ListExpr args)
|
|
{
|
|
string err =
|
|
"3x Orel, 2x CcInt, 1x CcReal expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,6))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no orel)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no orel)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no orel)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no CcInt)");
|
|
}
|
|
|
|
if(!CcReal::checkType(nl->Sixth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (sixth arg no CcReal");
|
|
}
|
|
|
|
// return the result type
|
|
return listutils::basicSymbol<CcInt>();
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlForwardSearchCreateAndAppendShortcutsTM(
|
|
ListExpr args)
|
|
{
|
|
string err =
|
|
"1x Orel, 2x CcInt, 1x CcReal expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,4))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no orel)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcReal::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no CcReal)");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetShortcutsCreatedSourceTypeInfo(),
|
|
relType);
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlForwardSearchProcessIncomingEdgeTM(
|
|
ListExpr args)
|
|
{
|
|
string err =
|
|
"4x Orel, 3x CcInt, 1x CcReal expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,8))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no CcInt)");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Sixth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (sixth arg no CcInt");
|
|
}
|
|
|
|
if(!CcInt::checkType(nl->Seventh(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (seventh arg no CcInt");
|
|
}
|
|
|
|
if(!CcReal::checkType(nl->Eigth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (eighth arg no CcReal");
|
|
}
|
|
|
|
// return the result type
|
|
return listutils::basicSymbol<CcInt>();
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlRemoveContractedEdgesFromEdgesRelationsTM(
|
|
ListExpr args)
|
|
{
|
|
string err = "2x Orel, 1x CcInt expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,3))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no CcInt)");
|
|
}
|
|
|
|
// return the result type
|
|
return listutils::basicSymbol<CcInt>();
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlRemoveParallelEdgesFromEdgesRelationsTM(
|
|
ListExpr args)
|
|
{
|
|
string err = "3x Orel expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,3))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no OrderedRelation)");
|
|
}
|
|
|
|
// return the result type
|
|
return listutils::basicSymbol<CcInt>();
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlDoContractionTM(ListExpr args)
|
|
{
|
|
string err = "2x Orel, 2x CcInt expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,4))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no CcInt)");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetShortcutsCreatedSourceTypeInfo(),
|
|
relType);
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlIterateOverAllNodesByRankAscAndDoContractionTM(
|
|
ListExpr args)
|
|
{
|
|
string err = "3x Orel, 1x CcInt expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,4))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no CcInt)");
|
|
}
|
|
|
|
// return the result type
|
|
return listutils::basicSymbol<CcInt>();
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlCreateLabelCheckForWitnessScanNewVerticesTM(
|
|
ListExpr args)
|
|
{
|
|
string err =
|
|
"2x Orel, 2x CcInt, 1x CcReal, 1xCcInt (bool) expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,6))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcReal::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no CcReal)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Sixth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (sixth arg no CcInt (bool))");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetNotYetVisitedNodesTypeInfo(),
|
|
relType);
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlCreateLabelCheckForWitnessTM(
|
|
ListExpr args)
|
|
{
|
|
string err =
|
|
"2x Orel, 1x rel, 2x CcInt, 1x CcReal, 1xCcInt (bool) expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,7))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!Relation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no Relation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcReal::checkType(nl->Sixth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (sixth arg no CcReal)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Seventh(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (seventh arg no CcInt (CcBool))");
|
|
}
|
|
|
|
// return the result type
|
|
return listutils::basicSymbol<CcInt>();
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlCreateLabelScanNewVerticesTM(
|
|
ListExpr args)
|
|
{
|
|
string err =
|
|
"2x Orel, 1x rel, 1x CcInt, 1x CcReal, 1x CcInt (CcBool) expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,6))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!Relation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no Relation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcReal::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no CcReal)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Sixth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (sixth arg no CcInt (CcBool))");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetNotYetVisitedNodesTypeInfo(),
|
|
relType);
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlGetRankByIdTM(ListExpr args)
|
|
{
|
|
string err =
|
|
"1x BTree, 1x Orel, 1x CcInt expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,3))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!BTree::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no BTree)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no CcInt)");
|
|
}
|
|
|
|
// return the result type
|
|
return listutils::basicSymbol<CcInt>();
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlCreateLabelByDijkstraWithStallingTM(
|
|
ListExpr args)
|
|
{
|
|
string err =
|
|
"1x BTree, 3x Orel, 2x CcInt, 1x CcInt (CcBool) expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,7))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!BTree::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no BTree)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Sixth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (sixth arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Seventh(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (seventh arg no CcInt (CcBool))");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetForwardOrReverseLabelTypeInfo(),
|
|
relType);
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlFillForwardOrReverseLabelTM(
|
|
ListExpr args)
|
|
{
|
|
string err = "1x Rel expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,1))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!Relation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no Relation)");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetAllLabelsTypeInfo(), relType);
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlGetPathViaPointsTM(ListExpr args)
|
|
{
|
|
string err =
|
|
"1x Nrel, 1x BTree, 1x Orel, 2x CcInt, 1x CcInt (CcBool) expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,6))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!NestedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no NestedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!BTree::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no BTree)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no CcInt)");
|
|
}
|
|
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (sixth arg no CcInt (CcBool))");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetEdgesRelTypeInfo(), relType);
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlQueryTM(ListExpr args)
|
|
{
|
|
string err =
|
|
"1x Nrel, 1x BTree, 2x Orel, 2x CcInt, 1x CcInt (CcBool) expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,7))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!NestedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no NestedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!BTree::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no BTree)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Sixth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (sixth arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Seventh(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (seventh arg no CcInt)");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetEdgesRelTypeInfo(), relType);
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlPruneLabelByBootstrappingTM(
|
|
ListExpr args)
|
|
{
|
|
string err = "3x Orel, 2x CcInt expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,5))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no CcInt)");
|
|
}
|
|
|
|
// return the result type
|
|
return listutils::basicSymbol<CcInt>();
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlReorderLabelsTM(ListExpr args)
|
|
{
|
|
string err = "3x Orel, 2x CcInt expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,5))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no CcInt)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no CcInt)");
|
|
}
|
|
|
|
// return the result type
|
|
return listutils::basicSymbol<CcInt>();
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlCreateLabelsTM(ListExpr args)
|
|
{
|
|
string err =
|
|
"1x BTree, 3x Orel, 1x CcInt expected.";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,5))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!BTree::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no BTree)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no CcInt)");
|
|
}
|
|
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetAllLabelsTypeInfo(), relType);
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
5.1.2 Type Mappings of (2) In-Memory Approach
|
|
|
|
*/
|
|
|
|
|
|
ListExpr hlTransformOrelToHlGraphTM(ListExpr args)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlTransformOrelToHlGraphTM" << endl);
|
|
#endif
|
|
|
|
|
|
|
|
string err = "2x orderedRelation";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,2))
|
|
{
|
|
return listutils::typeError(err + " (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetHlGraphOrelTypeInfo(),
|
|
relType);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlTransformOrelToHlGraphTM" << endl);
|
|
#endif
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlDoContractionOfHlGraphTM(ListExpr args)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlDoContractionOfHlGraphTM" << endl);
|
|
#endif
|
|
|
|
|
|
|
|
string err = "2x orderedRelation, 3x Int expected";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,5))
|
|
{
|
|
return listutils::typeError(err + " (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no Int)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no Int)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!CcInt::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no Int)");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetHlGraphOrelTypeInfo(),
|
|
relType);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlDoContractionOfHlGraphTM" << endl);
|
|
#endif
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlDoChSearchInHlGraphTM(ListExpr args)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlDoChSearchInHlGraphTM" << endl);
|
|
#endif
|
|
|
|
|
|
|
|
string err = "3x orel, 2x int expectd";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,5))
|
|
{
|
|
return listutils::typeError(err + " (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
if(!OrderedRelation::checkType(nl->Third(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (third arg no OrderedRelation)");
|
|
}
|
|
if(!CcInt::checkType(nl->Fourth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fourth arg no Int)");
|
|
}
|
|
if(!CcInt::checkType(nl->Fifth(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (fifth arg no Int)");
|
|
}
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetEdgesRelTypeInfo(),
|
|
relType);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlDoChSearchInHlGraphTM" << endl);
|
|
#endif
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlCalcWeightsOrelTM(ListExpr args)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlCalcWeightsOrelTM" << endl);
|
|
#endif
|
|
|
|
|
|
|
|
string err = "1x orel, 1x int expected";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,2))
|
|
{
|
|
return listutils::typeError(err + " (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
if(!CcInt::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no Int)");
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlCalcWeightsOrelTM" << endl);
|
|
#endif
|
|
|
|
// return the result type
|
|
return listutils::basicSymbol<CcInt>();
|
|
}
|
|
|
|
|
|
|
|
ListExpr hlCreateLabelsFromHlGraphTM(ListExpr args)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlCreateLabelsFromHlGraphTM" << endl);
|
|
#endif
|
|
|
|
|
|
|
|
string err = "2x orel expected";
|
|
|
|
// check the number of arguments
|
|
if(!nl->HasLength(args,2))
|
|
{
|
|
return listutils::typeError(err + " (wrong number of arguments)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->First(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (first arg no OrderedRelation)");
|
|
}
|
|
|
|
// check type of the argument
|
|
if(!OrderedRelation::checkType(nl->Second(args)))
|
|
{
|
|
return listutils::typeError(err +
|
|
" (second arg no OrderedRelation)");
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlCreateLabelsFromHlGraphTM" << endl);
|
|
#endif
|
|
|
|
// return the result type
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetAllLabelsTypeInfo(), relType);
|
|
|
|
return relType;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
5.1.3 Type Mappings of (3) In-Memory Approach using MainMemory2Algebra
|
|
|
|
not yet implemented
|
|
|
|
*/
|
|
|
|
/*
|
|
TODO: functions for doing ContractionHierarchies
|
|
using graph from existing Algebra MainMemory2
|
|
and its shortestPath implementations
|
|
Not working yet.
|
|
|
|
|
|
*/
|
|
ListExpr hlContractMmGraphTM(ListExpr args)
|
|
{
|
|
|
|
if(nl->ListLength(args) != 3) {
|
|
return listutils::typeError("three arguments expected");
|
|
}
|
|
|
|
//first: a graph
|
|
ListExpr graph1;
|
|
if(!mm2algebra::getMemSubType(nl->First(args), graph1)){
|
|
return listutils::typeError("first argument is not a memory object");
|
|
}
|
|
if(!mm2algebra::MemoryGraphObject::checkType(graph1)) {
|
|
return listutils::typeError("first arg is not a mem graph");
|
|
}
|
|
|
|
ListExpr graph1Tuple = nl->Second(graph1);
|
|
ListExpr graph1AttrList = (graph1Tuple);
|
|
if(nl->ListLength(graph1AttrList) < 3) {
|
|
return listutils::typeError("tuple of graph1 has less "
|
|
"than 3 attributes.");
|
|
}
|
|
|
|
//second
|
|
ListExpr graph2;
|
|
if(!mm2algebra::getMemSubType(nl->Second(args), graph2)){
|
|
return listutils::typeError("second arg is not a memory object");
|
|
}
|
|
if(!mm2algebra::MemoryGraphObject::checkType(graph2)) {
|
|
return listutils::typeError("second arg is not a mem graph2");
|
|
}
|
|
ListExpr graph2Tuple = nl->Second(graph2);
|
|
if(!nl->Equal(graph1Tuple,graph2Tuple)){
|
|
return listutils::typeError("Tuple Types of graphs differ");
|
|
}
|
|
|
|
//Check of third argument
|
|
|
|
ListExpr map = nl->Third(args);
|
|
if(!listutils::isMap<1>(map)) {
|
|
return listutils::typeError("third argument should be a map");
|
|
}
|
|
|
|
ListExpr mapTuple = nl->Second(map);
|
|
if(!nl->Equal(graph1Tuple, mapTuple)) {
|
|
return listutils::typeError(
|
|
"Tuple of map function must match graph tuple");
|
|
}
|
|
|
|
ListExpr mapres = nl->Third(map);
|
|
|
|
if(!CcReal::checkType(mapres)){
|
|
return listutils::typeError("result of the function is not a real");
|
|
}
|
|
|
|
// create output stream type
|
|
// corresponds to the graph tuples + SeqNo
|
|
|
|
ListExpr rest = graph1AttrList;
|
|
ListExpr listn = nl->OneElemList(nl->First(rest));
|
|
ListExpr lastlistn = listn;
|
|
rest = nl->Rest(rest);
|
|
while (!(nl->IsEmpty(rest))) {
|
|
lastlistn = nl->Append(lastlistn,nl->First(rest));
|
|
rest = nl->Rest(rest);
|
|
}
|
|
lastlistn = nl->Append(lastlistn,
|
|
nl->TwoElemList(
|
|
nl->SymbolAtom("SeqNo"),
|
|
nl->SymbolAtom(TupleIdentifier::BasicType())));
|
|
|
|
return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()),
|
|
nl->TwoElemList(
|
|
nl->SymbolAtom(Tuple::BasicType()),
|
|
listn));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
5.2 Value Mapping
|
|
|
|
The value mapping takes values as arguments and computes the result.
|
|
If the result of the operator is not a stream as here, the result storage of the
|
|
operator tree node must be used for returning the result. The arguments are
|
|
provided as an array of ~Word~ holding the arguments in the
|
|
~addr~ pointers. The type mapping ensures that only the expected types
|
|
are behind these pointers and the cast will be successful.
|
|
The parameters ~message~ and ~local~ are used for stream operators only.
|
|
The parameter ~s~ is the operator's node within the operator tree.
|
|
The result of the operator for non-stream operators is always 0.
|
|
|
|
The arguments are :
|
|
|
|
* ~args~: array with the arguments of the operator
|
|
|
|
* ~result~: output parameter, for non stream operators, the
|
|
result storage must be used
|
|
|
|
* ~message~: message used by stream operators
|
|
|
|
* ~local~: possibility to store the state of an operator, used in
|
|
stream operators
|
|
|
|
* ~s~: node of this operator within the operator tree
|
|
|
|
|
|
|
|
All ValueMappings are related to the equal named function of the
|
|
class HubLabelClass.
|
|
The ValueMappings just got an additional suffix 'VM'.
|
|
|
|
5.2.1 Value Mappings of (1) Persistent Approach
|
|
|
|
*/
|
|
|
|
|
|
|
|
int hlCalcRankVM (Word* args, Word& result,
|
|
int message,
|
|
Word& local, Supplier s)
|
|
{
|
|
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* orelEdgesSource =
|
|
(OrderedRelation*) args[0].addr;
|
|
OrderedRelation* orelEdgesTarget =
|
|
(OrderedRelation*) args[1].addr;
|
|
CcInt* nodeId = (CcInt*) args[2].addr;
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
CcReal* res = (CcReal*)
|
|
result.addr; // cast the result
|
|
res->Set(true, k->hlCalcRank(orelEdgesSource,
|
|
orelEdgesTarget,
|
|
HubLabelClass::HL_DEFAULT_CALC_FUNCTION,
|
|
nodeId)); // compute and set the result
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int hlOneHopReverseSearchVM (Word* args,
|
|
Word& result, int message, Word& local,
|
|
Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlOneHopReverseSearchVM" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* orelEdgesSource =
|
|
(OrderedRelation*) args[0].addr;
|
|
OrderedRelation* orelEdgesTarget =
|
|
(OrderedRelation*) args[1].addr;
|
|
CcInt* nodeId = (CcInt*) args[2].addr;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
OrderedRelation* oneHopReverseOrelId =
|
|
(OrderedRelation*) result.addr; // cast the result
|
|
|
|
if(oneHopReverseOrelId->GetNoTuples() > 0)
|
|
{
|
|
//Relation leeren, falls alte Daten aus vorheriger
|
|
// Durchführung noch enthalten sind
|
|
oneHopReverseOrelId->Clear();
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("do hlOneHopReverseSearch" << endl);
|
|
#endif
|
|
std::multimap<int, std::tuple<int, double>>
|
|
oneHopReverseMultimap;
|
|
k->hlOneHopReverseSearch(orelEdgesSource,
|
|
orelEdgesTarget, nodeId, oneHopReverseMultimap);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("Add elements from oneHopReverseMultimap to oneHopReverseOrelId"
|
|
<< endl);
|
|
#endif
|
|
for (std::multimap<int, std::tuple<int, double>>::iterator
|
|
oneHopReverseMultimapIter =
|
|
oneHopReverseMultimap.begin();
|
|
oneHopReverseMultimapIter !=
|
|
oneHopReverseMultimap.end();
|
|
++oneHopReverseMultimapIter)
|
|
{
|
|
std::tuple<int, double> currTuple =
|
|
(*oneHopReverseMultimapIter).second;
|
|
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetOneHopReverseOrelIdTypeInfo(),
|
|
relType); //TODO: passt das? das ist ein orel type info,
|
|
// kein tuple type info
|
|
ListExpr tupNumType =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relType));//TODO: passt das?
|
|
Tuple* insertTuple = new Tuple(
|
|
tupNumType);//num type verwenden oder nicht?
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE,
|
|
new CcInt(true,
|
|
(*oneHopReverseMultimapIter).first));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE,
|
|
new CcInt(true,
|
|
std::get<HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE
|
|
- 1>(currTuple)));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE,
|
|
new CcReal(true,
|
|
std::get<HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE
|
|
- 1>(currTuple)));
|
|
oneHopReverseOrelId->AppendTuple(insertTuple);
|
|
insertTuple->DeleteIfAllowed(); //TODO: warum muss der Tuple
|
|
// gelöscht werden? wird er per beim Append geklont? Nicht dass
|
|
// das Löschen hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlOneHopReverseSearchVM" << endl);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int hlHHopForwardSearchVM (Word* args,
|
|
Word& result, int message, Word& local,
|
|
Supplier s)
|
|
{
|
|
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* orelEdgesSource =
|
|
(OrderedRelation*) args[0].addr;
|
|
OrderedRelation* orelEdgesTarget =
|
|
(OrderedRelation*) args[1].addr;
|
|
OrderedRelation* reverseSearchOrelXT =
|
|
(OrderedRelation*) args[2].addr;
|
|
CcInt* nodeIdV = (CcInt*) args[3].addr;
|
|
CcInt* hHopCcInt = (CcInt*) args[4].addr;
|
|
|
|
int hHopInt = hHopCcInt->GetIntval();
|
|
if(hHopInt < 0)
|
|
{
|
|
hHopInt = HubLabelClass::HL_DEFAULT_H_DEPTH;
|
|
}
|
|
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
OrderedRelation*
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted =
|
|
(OrderedRelation*) result.addr; // cast the result
|
|
|
|
std::multimap<int, std::tuple<int, double, int>>
|
|
shortcutsMultimap;
|
|
|
|
//Convert OrderedRelation to MultiMap
|
|
GenericRelationIterator* reverseSearchOrelXTIter =
|
|
reverseSearchOrelXT->MakeScan();
|
|
Tuple* currTuple1 =
|
|
reverseSearchOrelXTIter->GetNextTuple();
|
|
|
|
std::multimap<int, std::tuple<int, double>>
|
|
multimapReverseSearchXT;
|
|
while(currTuple1)
|
|
{
|
|
CcInt* currTupleIdU = (CcInt*)
|
|
currTuple1->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE);
|
|
CcInt* currTupleIdT = (CcInt*)
|
|
currTuple1->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE);
|
|
CcReal* currTupleDistUT = (CcReal*)
|
|
currTuple1->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE);
|
|
|
|
std::tuple<int, double> insertTuple =
|
|
std::make_tuple(currTupleIdT->GetIntval(),
|
|
currTupleDistUT->GetRealval());
|
|
//num type verwenden oder nicht?
|
|
multimapReverseSearchXT.insert(
|
|
pair<int, std::tuple<int, double>>
|
|
(currTupleIdU->GetIntval(), insertTuple));
|
|
|
|
//Free Outgoing-Iteration
|
|
currTuple1->DeleteIfAllowed(); //TODO: ist delete ok,
|
|
// wenn zuvor einer anderen orel zugewiesen oder wird das
|
|
// tuple aus der neuen orel dann auch gelöscht?
|
|
currTuple1 = 0;
|
|
currTuple1 =
|
|
reverseSearchOrelXTIter->GetNextTuple();
|
|
}
|
|
delete reverseSearchOrelXTIter;
|
|
|
|
k->hlHHopForwardSearch(orelEdgesSource,
|
|
orelEdgesTarget, multimapReverseSearchXT, nodeIdV,
|
|
shortcutsMultimap,
|
|
hHopInt); // compute and set the result
|
|
|
|
//convert multimap back to OrderedRelation
|
|
for (std::multimap<int, std::tuple<int, double, int>>::iterator
|
|
shortcutsMultimapIter = shortcutsMultimap.begin();
|
|
shortcutsMultimapIter != shortcutsMultimap.end();
|
|
++shortcutsMultimapIter)
|
|
{
|
|
std::tuple<int, double, int> currTuple2 =
|
|
(*shortcutsMultimapIter).second;
|
|
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetShortcutsCreatedSourceTypeInfo(),
|
|
relType); //TODO: passt das? das ist ein orel type info,
|
|
// kein tuple type info
|
|
ListExpr tupNumType =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relType));//TODO: passt das?
|
|
Tuple* insertTuple1 = new Tuple(
|
|
tupNumType);//num type verwenden oder nicht?
|
|
insertTuple1->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_SOURCE_IN_SHORTCUT_TUPLE,
|
|
new CcInt(true, (*shortcutsMultimapIter).first));
|
|
insertTuple1->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_TARGET_IN_SHORTCUT_TUPLE,
|
|
new CcInt(true,
|
|
std::get<HubLabelClass::HL_INDEX_OF_TARGET_IN_SHORTCUT_TUPLE
|
|
- 1>(currTuple2)));
|
|
insertTuple1->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_SHORTCUT_TUPLE,
|
|
new CcReal(true,
|
|
std::get<HubLabelClass::HL_INDEX_OF_DIST_IN_SHORTCUT_TUPLE
|
|
- 1>(currTuple2)));
|
|
insertTuple1->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_PARENT_ID_IN_SHORTCUT_TUPLE,
|
|
new CcInt(true,
|
|
std::get<HubLabelClass::HL_INDEX_OF_PARENT_ID_IN_SHORTCUT_TUPLE
|
|
- 1>(currTuple2)));
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted->AppendTuple(
|
|
insertTuple1);
|
|
insertTuple1->DeleteIfAllowed(); //TODO: warum muss der Tuple gelöscht
|
|
// werden? wird er per beim Append geklont? Nicht dass das Löschen
|
|
// hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int hlForwardSearchGetDistVM (Word* args,
|
|
Word& result, int message, Word& local,
|
|
Supplier s)
|
|
{
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* reverseSearchEdgeSourceOrelXT =
|
|
(OrderedRelation*) args[0].addr;
|
|
CcInt* currentNodeIdV = (CcInt*) args[1].addr;
|
|
CcInt* currentNodeIdT = (CcInt*) args[2].addr;
|
|
|
|
//Convert OrderedRelation to MultiMap
|
|
GenericRelationIterator*
|
|
reverseSearchEdgeSourceOrelXTIter =
|
|
reverseSearchEdgeSourceOrelXT->MakeScan();
|
|
Tuple* currTuple1 =
|
|
reverseSearchEdgeSourceOrelXTIter->GetNextTuple();
|
|
|
|
std::multimap<int, std::tuple<int, double>>
|
|
reverseSearchMultimap;
|
|
while(currTuple1)
|
|
{
|
|
CcInt* currTupleIdU = (CcInt*)
|
|
currTuple1->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE);
|
|
CcInt* currTupleIdT = (CcInt*)
|
|
currTuple1->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE);
|
|
CcReal* currTupleDistUT = (CcReal*)
|
|
currTuple1->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE);
|
|
|
|
std::tuple<int, double> insertTuple =
|
|
std::make_tuple(currTupleIdT->GetIntval(),
|
|
currTupleDistUT->GetRealval());
|
|
//num type verwenden oder nicht?
|
|
reverseSearchMultimap.insert(
|
|
pair<int, std::tuple<int, double>>
|
|
(currTupleIdU->GetIntval(), insertTuple));
|
|
|
|
//Free Outgoing-Iteration
|
|
currTuple1->DeleteIfAllowed(); //TODO: ist delete ok, wenn
|
|
// zuvor einer anderen orel zugewiesen oder wird das tuple aus
|
|
// der neuen orel dann auch gelöscht?
|
|
currTuple1 = 0;
|
|
currTuple1 =
|
|
reverseSearchEdgeSourceOrelXTIter->GetNextTuple();
|
|
}
|
|
delete reverseSearchEdgeSourceOrelXTIter;
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
CcReal* res = (CcReal*)
|
|
result.addr; // cast the result
|
|
res->Set(true, k->hlForwardSearchGetDistVT(
|
|
reverseSearchMultimap,
|
|
currentNodeIdV->GetIntval(),
|
|
currentNodeIdT->GetIntval()));
|
|
// compute and set the result
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int hlRemoveTFromCurrentWitnessListVM (Word* args,
|
|
Word& result, int message, Word& local,
|
|
Supplier s)
|
|
{
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* witnessList = (OrderedRelation*)
|
|
args[0].addr;
|
|
CcInt* currNodeIdT = (CcInt*) args[1].addr;
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
OrderedRelation* reducedWitnessLiestOrel =
|
|
(OrderedRelation*) result.addr; // cast the result
|
|
|
|
//insert all tuples from given orel into result orel
|
|
GenericRelationIterator* witnessListIter =
|
|
witnessList->MakeScan();
|
|
Tuple* currTuple =
|
|
witnessListIter->GetNextTuple();
|
|
|
|
while(currTuple)
|
|
{
|
|
reducedWitnessLiestOrel->AppendTuple(currTuple);
|
|
|
|
//Free Outgoing-Iteration
|
|
currTuple->DeleteIfAllowed(); //TODO: ist delete ok, wenn zuvor
|
|
// einer anderen orel zugewiesen oder wird das tuple aus der
|
|
// neuen orel dann auch gelöscht?
|
|
currTuple = 0;
|
|
currTuple = witnessListIter->GetNextTuple();
|
|
}
|
|
|
|
delete witnessListIter;
|
|
|
|
k->hlRemoveTuplesFromOrel(reducedWitnessLiestOrel,
|
|
currNodeIdT->GetIntval(),
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE);
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int hlForwardSearchCheckForWitnessPathVM (
|
|
Word* args, Word& result, int message,
|
|
Word& local, Supplier s)
|
|
{
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* witnessList = (OrderedRelation*)
|
|
args[0].addr;
|
|
CcInt* currNodeIdV = (CcInt*) args[1].addr;
|
|
CcInt* currNodeIdX = (CcInt*) args[2].addr;
|
|
CcReal* distSX = (CcReal*) args[3].addr;
|
|
CcReal* distSV = (CcReal*) args[4].addr;
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
OrderedRelation* reducedWitnessListOrel =
|
|
(OrderedRelation*) result.addr; // cast the result
|
|
|
|
//Convert OrderedRelation to MultiMap
|
|
GenericRelationIterator* witnessListIter =
|
|
witnessList->MakeScan();
|
|
Tuple* currTuple =
|
|
witnessListIter->GetNextTuple();
|
|
|
|
std::multimap<int, std::tuple<int, double>>
|
|
oneHopReverseMultimap;
|
|
while(currTuple)
|
|
{
|
|
CcInt* currTupleIdU = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE);
|
|
CcInt* currTupleIdT = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE);
|
|
CcReal* currTupleDistUT = (CcReal*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE);
|
|
|
|
std::tuple<int, double> insertTuple =
|
|
std::make_tuple(currTupleIdT->GetIntval(),
|
|
currTupleDistUT->GetRealval());
|
|
//num type verwenden oder nicht?
|
|
oneHopReverseMultimap.insert(
|
|
pair<int, std::tuple<int, double>>
|
|
(currTupleIdU->GetIntval(), insertTuple));
|
|
|
|
//Free Outgoing-Iteration
|
|
currTuple->DeleteIfAllowed(); //TODO: ist delete ok, wenn
|
|
// zuvor einer anderen orel zugewiesen oder wird das tuple aus
|
|
// der neuen orel dann auch gelöscht?
|
|
currTuple = 0;
|
|
currTuple = witnessListIter->GetNextTuple();
|
|
}
|
|
|
|
delete witnessListIter;
|
|
|
|
k->hlForwardSearchCheckForWitnessPath(
|
|
oneHopReverseMultimap, currNodeIdV->GetIntval(),
|
|
currNodeIdX->GetIntval(), distSX->GetRealval(),
|
|
distSV->GetRealval());
|
|
|
|
//convert multimap back to OrderedRelation
|
|
for (std::multimap<int, std::tuple<int, double>>::iterator
|
|
oneHopReverseMultimapIter =
|
|
oneHopReverseMultimap.begin();
|
|
oneHopReverseMultimapIter !=
|
|
oneHopReverseMultimap.end();
|
|
++oneHopReverseMultimapIter)
|
|
{
|
|
std::tuple<int, double> currTuple =
|
|
(*oneHopReverseMultimapIter).second;
|
|
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetOneHopReverseOrelIdTypeInfo(),
|
|
relType); //TODO: passt das? das ist ein orel type info,
|
|
// kein tuple type info
|
|
ListExpr tupNumType =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relType));//TODO: passt das?
|
|
Tuple* insertTuple = new Tuple(
|
|
tupNumType);//num type verwenden oder nicht?
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE,
|
|
new CcInt(true,
|
|
(*oneHopReverseMultimapIter).first));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE,
|
|
new CcInt(true,
|
|
std::get<HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE
|
|
- 1>(currTuple)));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE,
|
|
new CcReal(true,
|
|
std::get<HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE
|
|
- 1>(currTuple)));
|
|
reducedWitnessListOrel->AppendTuple(insertTuple);
|
|
insertTuple->DeleteIfAllowed(); //TODO: warum muss der Tuple
|
|
// gelöscht werden? wird er per beim Append geklont? Nicht dass das
|
|
// Löschen hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
Erwartet eine relEdgesSource bei der die enthaltenen Edges in der
|
|
Reihenfolge der rel auch in diesem Test-Operator verarbeitet
|
|
werden sollen.
|
|
Der 3. Parameter enthält die ID für den Startknoten, dieser
|
|
erkennt alle Edges der rel,
|
|
die vom Startknoten aus weggehen.
|
|
|
|
Folgende Testfälle sollten (jedoch in beliebiger Reihenfolge)
|
|
enthalten sein:
|
|
|
|
Die Erste Edge sollte S->V sein, es wird erwartet, dass diese nicht
|
|
eingefügt wird.
|
|
Die zweite Edge sollte S->W sein, es wird erwartet, dass diese eingefügt
|
|
wird.
|
|
Die dritte Edge sollte W->X sein, es wird erwartet, dass diese eingefügt
|
|
wird.
|
|
Die folgenden Edges sollten X1->X2 sein, es wird erwartet, dass diese
|
|
eingefügt werden.
|
|
Die nächste Edge sollte X3->X4 sein, wobei X4 bereits in der Orel enthalten
|
|
sein soll (hier U genannt),
|
|
der Weg S->X4 sollte länger sein, als der bisherige Weg S->U, es erwartet,
|
|
dass diese edge nicht eingefügt wird.
|
|
Die folgenden Edges sollten X1->X2 sein, es wird erwartet, dass diese
|
|
eingefügt werden.
|
|
Die nächste Edge sollte X5->X6 sein, wobei X6 bereits in der Orel
|
|
enthalten sein soll (hier U2 genannt),
|
|
der Weg S->X6 sollte kürzer sein, als der bisherige Weg S->U2,
|
|
es erwartet, dass diese edge eingefügt wird.
|
|
Es sollten keine weiteren Edges im Input enthalten sein.
|
|
Die Orel wird an die Query zurückgegeben.
|
|
|
|
|
|
*/
|
|
int hlInsertOrUpdateTupleInNotYetVisitedListVM (
|
|
Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
Relation* edgesRelSource = (Relation*)
|
|
args[0].addr;
|
|
CcInt* currNodeIdS = (CcInt*) args[1].addr;
|
|
CcInt* currNodeIdV = (CcInt*) args[2].addr;
|
|
CcBool* isForward = (CcBool*) args[3].addr;
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
OrderedRelation* notYetVisitedOrel =
|
|
(OrderedRelation*) result.addr;
|
|
// cast the result
|
|
|
|
//get next edge (s, w)
|
|
GenericRelationIterator* edgesRelSourceIter =
|
|
edgesRelSource->MakeScan();
|
|
Tuple* nextTuple =
|
|
edgesRelSourceIter->GetNextTuple();
|
|
|
|
std::multimap<double, std::tuple<int, int>>
|
|
notYetVisitedNodesMultiMap;
|
|
|
|
//iterate over all given edges in the given input order
|
|
while(nextTuple)
|
|
{
|
|
CcInt* nextTupleSourceId = (CcInt*)
|
|
nextTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
|
|
//create minW tuple from the source of the current edge iterated (
|
|
//so force the source to be the current minW also if it actually isnt)
|
|
std::tuple<double, int, int>
|
|
currMinNotYetVisitedNodeTuple;
|
|
bool callFunction = false;
|
|
|
|
//Dont insert something when no source had been inserted befire
|
|
//Special call of the function if the actual source node s
|
|
// shall be inserted
|
|
//If there are entries call insert or update which may leads to
|
|
// a insertion, an update or no change at all
|
|
//do so for every iteration of the given relation
|
|
if(nextTupleSourceId->GetIntval() ==
|
|
currNodeIdS->GetIntval())
|
|
{
|
|
currMinNotYetVisitedNodeTuple = std::make_tuple(
|
|
0.0,
|
|
nextTupleSourceId->GetIntval(), 0);
|
|
callFunction = true;
|
|
}
|
|
else if(notYetVisitedNodesMultiMap.size() > 0)
|
|
{
|
|
//get Tuple with min(dist)
|
|
std::multimap<double, std::tuple<int, int>>::iterator
|
|
notYetVisitedNodesMultiMapIter =
|
|
notYetVisitedNodesMultiMap.begin();
|
|
double currMinDist =
|
|
(*notYetVisitedNodesMultiMapIter).first;
|
|
|
|
std::tuple<int, int> currTuple =
|
|
(*notYetVisitedNodesMultiMapIter).second;
|
|
int currMinNodeId = std::get<
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED
|
|
- 1>(currTuple);
|
|
int currMinHopDepth = std::get<
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED
|
|
- 1>(currTuple);
|
|
|
|
//Create auxiliary tuple
|
|
currMinNotYetVisitedNodeTuple = std::make_tuple(
|
|
currMinDist,
|
|
currMinNodeId, currMinHopDepth);
|
|
callFunction = true;
|
|
}
|
|
|
|
//insert edge (s, w)
|
|
if(callFunction == true)
|
|
{
|
|
bool isHHop = true;
|
|
k->hlInsertOrUpdateTupleInNotYetVisitedList(
|
|
currNodeIdV->GetIntval(),
|
|
currMinNotYetVisitedNodeTuple,
|
|
nextTuple, notYetVisitedNodesMultiMap,
|
|
isForward->GetBoolval(),
|
|
isHHop);
|
|
}
|
|
|
|
nextTuple->DeleteIfAllowed();
|
|
nextTuple = 0;
|
|
nextTuple = edgesRelSourceIter->GetNextTuple();
|
|
}
|
|
|
|
//convert multimap back to OrderedRelation
|
|
for (std::multimap<double, std::tuple<int, int>>::iterator
|
|
notYetVisitedNodesMultiMapIter =
|
|
notYetVisitedNodesMultiMap.begin();
|
|
notYetVisitedNodesMultiMapIter !=
|
|
notYetVisitedNodesMultiMap.end();
|
|
++notYetVisitedNodesMultiMapIter)
|
|
{
|
|
std::tuple<int, int> currTupleConvert =
|
|
(*notYetVisitedNodesMultiMapIter).second;
|
|
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetNotYetVisitedNodesTypeInfo(),
|
|
relType);
|
|
//TODO: passt das? das ist ein orel type info, kein tuple type info
|
|
ListExpr tupNumType =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relType));
|
|
//TODO: passt das?
|
|
Tuple* insertTuple = new Tuple(tupNumType);
|
|
//num type verwenden oder nicht?
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_NOT_YET_VISITED,
|
|
new CcReal(true,
|
|
(*notYetVisitedNodesMultiMapIter).first));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED
|
|
- 1>(currTupleConvert)));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED
|
|
- 1>(currTupleConvert)));
|
|
notYetVisitedOrel->AppendTuple(insertTuple);
|
|
insertTuple->DeleteIfAllowed();
|
|
//TODO: warum muss der Tuple gelöscht werden?
|
|
// wird er per beim Append geklont? Nicht dass das Löschen
|
|
// hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
//free resources
|
|
delete edgesRelSourceIter;
|
|
delete k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlForwardSearchIterativeStepsScanNewVerticesVM (
|
|
Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* orelEdgesSource =
|
|
(OrderedRelation*) args[0].addr;
|
|
OrderedRelation* notYetVisitedNodesOrel =
|
|
(OrderedRelation*) args[1].addr;
|
|
OrderedRelation* stillVisitedNodesOrel =
|
|
(OrderedRelation*) args[2].addr;
|
|
OrderedRelation* copyMultimapReverseSearchXT =
|
|
(OrderedRelation*) args[3].addr;
|
|
Relation* currMinSingleTupleRelW =
|
|
(Relation*) args[4].addr;
|
|
CcInt* currNodeIdV = (CcInt*) args[5].addr;
|
|
CcReal* distSV = (CcReal*) args[6].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
CcInt* resultInt = (CcInt*)
|
|
result.addr; // cast the result
|
|
resultInt->Set(true, 1);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
//minW Tuple aus Container-Relation auslesen
|
|
GenericRelationIterator*
|
|
currMinSingleTupleRelWIter =
|
|
currMinSingleTupleRelW->MakeScan();
|
|
Tuple* currMinSingleTupleRelWTuple =
|
|
currMinSingleTupleRelWIter->GetNextTuple();
|
|
delete currMinSingleTupleRelWIter;
|
|
|
|
if(!currMinSingleTupleRelWTuple)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("kein Tuple, komisch" << endl);
|
|
#endif
|
|
}
|
|
CcReal* currMinDist = (CcReal*)
|
|
currMinSingleTupleRelWTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_NOT_YET_VISITED);
|
|
CcInt* currMinNodeId = (CcInt*)
|
|
currMinSingleTupleRelWTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED);
|
|
CcInt* currMinHopDepth = (CcInt*)
|
|
currMinSingleTupleRelWTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED);
|
|
|
|
std::tuple<double, int, int>
|
|
currMinNotYetVisitedNodeTuple =
|
|
std::make_tuple(currMinDist->GetRealval(),
|
|
currMinNodeId->GetIntval(),
|
|
currMinHopDepth->GetIntval());
|
|
|
|
currMinSingleTupleRelWTuple->DeleteIfAllowed();
|
|
currMinSingleTupleRelWTuple = 0;
|
|
|
|
|
|
|
|
//convert OrderedRelation to multimap notYetVisited
|
|
std::multimap<double, std::tuple<int, int>>
|
|
notYetVisitedNodesMultiMap;
|
|
GenericRelationIterator*
|
|
notYetVisitedOrelResultIter =
|
|
notYetVisitedNodesOrel->MakeScan();
|
|
Tuple* notYetOrelTuple =
|
|
notYetVisitedOrelResultIter->GetNextTuple();
|
|
|
|
while(notYetOrelTuple)
|
|
{
|
|
CcReal* currNotYetDist = (CcReal*)
|
|
notYetOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_NOT_YET_VISITED);
|
|
CcInt* currNotYetNodeId = (CcInt*)
|
|
notYetOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED);
|
|
CcInt* currNotYetHopDepth = (CcInt*)
|
|
notYetOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED);
|
|
|
|
std::tuple<int, double> insertMultimapTupleNotYet
|
|
= std::make_tuple(
|
|
currNotYetNodeId->GetIntval(),
|
|
currNotYetHopDepth->GetIntval());
|
|
//num type verwenden oder nicht?
|
|
notYetVisitedNodesMultiMap.insert(
|
|
pair<double, std::tuple<int, int>>(
|
|
currNotYetDist->GetRealval(),
|
|
insertMultimapTupleNotYet));
|
|
|
|
notYetOrelTuple->DeleteIfAllowed();
|
|
notYetOrelTuple = 0;
|
|
notYetOrelTuple =
|
|
notYetVisitedOrelResultIter->GetNextTuple();
|
|
}
|
|
|
|
//free resources
|
|
delete notYetVisitedOrelResultIter;
|
|
|
|
|
|
|
|
//Convert OrderedRelation to unordered_set stillVisitedNodes
|
|
GenericRelationIterator* stillVisitedNodesOrelIter
|
|
=
|
|
stillVisitedNodesOrel->MakeScan();
|
|
Tuple* currStillVisitedOrelTuple =
|
|
stillVisitedNodesOrelIter->GetNextTuple();
|
|
|
|
std::unordered_set<int> stillVisitedNodesSet;
|
|
while(currStillVisitedOrelTuple)
|
|
{
|
|
CcInt* currStillVisitedTupleId = (CcInt*)
|
|
currStillVisitedOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_STILL_VISITED);
|
|
stillVisitedNodesSet.insert(
|
|
currStillVisitedTupleId->GetIntval());
|
|
|
|
//Free Outgoing-Iteration
|
|
currStillVisitedOrelTuple->DeleteIfAllowed();
|
|
currStillVisitedOrelTuple = 0;
|
|
currStillVisitedOrelTuple =
|
|
stillVisitedNodesOrelIter->GetNextTuple();
|
|
}
|
|
|
|
delete stillVisitedNodesOrelIter;
|
|
|
|
|
|
|
|
//Convert OrderedRelation to MultiMap reverseSearch
|
|
std::multimap<int, std::tuple<int, double>>
|
|
oneHopReverseMultimap;
|
|
GenericRelationIterator*
|
|
copyMultimapReverseSearchXTIter =
|
|
copyMultimapReverseSearchXT->MakeScan();
|
|
Tuple* currReverseOrelTuple =
|
|
copyMultimapReverseSearchXTIter->GetNextTuple();
|
|
|
|
while(currReverseOrelTuple)
|
|
{
|
|
CcInt* currReverseTupleIdU = (CcInt*)
|
|
currReverseOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE);
|
|
CcInt* currReverseTupleIdT = (CcInt*)
|
|
currReverseOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE);
|
|
CcReal* currReverseTupleDistUT = (CcReal*)
|
|
currReverseOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE);
|
|
|
|
std::tuple<int, double> reverseInsertMultimapTuple
|
|
= std::make_tuple(
|
|
currReverseTupleIdT->GetIntval(),
|
|
currReverseTupleDistUT->GetRealval());
|
|
//num type verwenden oder nicht?
|
|
|
|
oneHopReverseMultimap.insert(
|
|
pair<int, std::tuple<int, double>>(
|
|
currReverseTupleIdU->GetIntval(),
|
|
reverseInsertMultimapTuple));
|
|
|
|
//Free Outgoing-Iteration
|
|
currReverseOrelTuple->DeleteIfAllowed();
|
|
//TODO: ist delete ok, wenn zuvor einer anderen orel
|
|
// zugewiesen oder wird das tuple aus der neuen orel dann
|
|
// auch gelöscht?
|
|
currReverseOrelTuple = 0;
|
|
currReverseOrelTuple =
|
|
copyMultimapReverseSearchXTIter->GetNextTuple();
|
|
}
|
|
|
|
delete copyMultimapReverseSearchXTIter;
|
|
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
k->hlForwardSearchIterativeStepsScanNewVertices(
|
|
orelEdgesSource,
|
|
currNodeIdV->GetIntval(),
|
|
currMinNotYetVisitedNodeTuple,
|
|
notYetVisitedNodesMultiMap, stillVisitedNodesSet,
|
|
oneHopReverseMultimap,
|
|
distSV->GetRealval());
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
|
|
|
|
//convert multimap back to OrderedRelation notYetVisitedNodes
|
|
notYetVisitedNodesOrel->Clear();
|
|
for (std::multimap<double, std::tuple<int, int>>::iterator
|
|
notYetVisitedNodesMultiMapIter =
|
|
notYetVisitedNodesMultiMap.begin();
|
|
notYetVisitedNodesMultiMapIter !=
|
|
notYetVisitedNodesMultiMap.end();
|
|
++notYetVisitedNodesMultiMapIter)
|
|
{
|
|
std::tuple<int, int> currTupleConvert =
|
|
(*notYetVisitedNodesMultiMapIter).second;
|
|
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetNotYetVisitedNodesTypeInfo(),
|
|
relType);
|
|
//TODO: passt das? das ist ein orel type info, kein tuple type info
|
|
ListExpr tupNumType =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relType));
|
|
//TODO: passt das?
|
|
Tuple* notYetInsertOrelTuple = new Tuple(
|
|
tupNumType);
|
|
//num type verwenden oder nicht?
|
|
notYetInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_NOT_YET_VISITED,
|
|
new CcReal(true,
|
|
(*notYetVisitedNodesMultiMapIter).first));
|
|
notYetInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED
|
|
- 1>(currTupleConvert)));
|
|
notYetInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED
|
|
- 1>(currTupleConvert)));
|
|
notYetVisitedNodesOrel->AppendTuple(
|
|
notYetInsertOrelTuple);
|
|
notYetInsertOrelTuple->DeleteIfAllowed();
|
|
//TODO: warum muss der Tuple gelöscht werden?
|
|
// wird er per beim Append geklont? Nicht dass das Löschen
|
|
// hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
//convert multimap back to OrderedRelation notYetVisitedNodes
|
|
copyMultimapReverseSearchXT->Clear();
|
|
for (std::multimap<int, std::tuple<int, double>>::iterator
|
|
oneHopReverseMultimapIter =
|
|
oneHopReverseMultimap.begin();
|
|
oneHopReverseMultimapIter !=
|
|
oneHopReverseMultimap.end();
|
|
++oneHopReverseMultimapIter)
|
|
{
|
|
std::tuple<int, double> currTupleConvertReverse =
|
|
(*oneHopReverseMultimapIter).second;
|
|
|
|
ListExpr relTypeReverse;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetOneHopReverseOrelIdTypeInfo(),
|
|
relTypeReverse);
|
|
//TODO: passt das? das ist ein orel type info, kein tuple type info
|
|
ListExpr tupNumTypeReverse =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relTypeReverse));
|
|
//TODO: passt das?
|
|
Tuple* reverseInsertOrelTuple = new Tuple(
|
|
tupNumTypeReverse);
|
|
//num type verwenden oder nicht?
|
|
reverseInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE,
|
|
new CcInt(true,
|
|
(*oneHopReverseMultimapIter).first));
|
|
reverseInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE
|
|
- 1>(currTupleConvertReverse)));
|
|
reverseInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE,
|
|
new CcReal(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE
|
|
- 1>(currTupleConvertReverse)));
|
|
copyMultimapReverseSearchXT->AppendTuple(
|
|
reverseInsertOrelTuple);
|
|
reverseInsertOrelTuple->DeleteIfAllowed();
|
|
//TODO: warum muss der Tuple gelöscht werden?
|
|
// wird er per beim Append geklont? Nicht dass das Löschen hier den
|
|
// Tuple in der Relation zerstört.
|
|
}
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
//Änderungen an als Parameter übergebenen Orels persistieren
|
|
qp->SetModified(qp->GetSon(s,1));
|
|
qp->SetModified(qp->GetSon(s,3));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlForwardSearchProcessIncomingEdgeIterativeStepsVM (
|
|
Word* args,
|
|
Word& result, int message, Word& local,
|
|
Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* orelEdgesSource =
|
|
(OrderedRelation*) args[0].addr;
|
|
OrderedRelation* notYetVisitedNodesOrel =
|
|
(OrderedRelation*) args[1].addr;
|
|
OrderedRelation* stillVisitedNodesOrel =
|
|
(OrderedRelation*) args[2].addr;
|
|
OrderedRelation* copyMultimapReverseSearchXT =
|
|
(OrderedRelation*) args[3].addr;
|
|
CcInt* hHop = (CcInt*) args[4].addr;
|
|
CcInt* currNodeIdV = (CcInt*) args[5].addr;
|
|
CcReal* distSV = (CcReal*) args[6].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
CcInt* resultInt = (CcInt*)
|
|
result.addr; // cast the result
|
|
resultInt->Set(true, 1);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
|
|
//convert OrderedRelation to multimap notYetVisited
|
|
std::multimap<double, std::tuple<int, int>>
|
|
notYetVisitedNodesMultiMap;
|
|
GenericRelationIterator*
|
|
notYetVisitedOrelResultIter =
|
|
notYetVisitedNodesOrel->MakeScan();
|
|
Tuple* notYetOrelTuple =
|
|
notYetVisitedOrelResultIter->GetNextTuple();
|
|
|
|
while(notYetOrelTuple)
|
|
{
|
|
CcReal* currNotYetDist = (CcReal*)
|
|
notYetOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_NOT_YET_VISITED);
|
|
CcInt* currNotYetNodeId = (CcInt*)
|
|
notYetOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED);
|
|
CcInt* currNotYetHopDepth = (CcInt*)
|
|
notYetOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED);
|
|
|
|
std::tuple<int, int> insertMultimapTupleNotYet =
|
|
std::make_tuple(
|
|
currNotYetNodeId->GetIntval(),
|
|
currNotYetHopDepth->GetIntval());
|
|
//num type verwenden oder nicht?
|
|
notYetVisitedNodesMultiMap.insert(
|
|
pair<double, std::tuple<int, int>>(
|
|
currNotYetDist->GetRealval(),
|
|
insertMultimapTupleNotYet));
|
|
|
|
notYetOrelTuple->DeleteIfAllowed();
|
|
notYetOrelTuple = 0;
|
|
notYetOrelTuple =
|
|
notYetVisitedOrelResultIter->GetNextTuple();
|
|
}
|
|
|
|
//free resources
|
|
delete notYetVisitedOrelResultIter;
|
|
|
|
|
|
|
|
//Convert OrderedRelation to unordered_set stillVisitedNodes
|
|
std::unordered_set<int> stillVisitedNodesSet;
|
|
GenericRelationIterator* stillVisitedNodesOrelIter
|
|
=
|
|
stillVisitedNodesOrel->MakeScan();
|
|
Tuple* currStillVisitedOrelTuple =
|
|
stillVisitedNodesOrelIter->GetNextTuple();
|
|
|
|
while(currStillVisitedOrelTuple)
|
|
{
|
|
CcInt* currStillVisitedTupleId = (CcInt*)
|
|
currStillVisitedOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_STILL_VISITED);
|
|
stillVisitedNodesSet.insert(
|
|
currStillVisitedTupleId->GetIntval());
|
|
|
|
//Free Outgoing-Iteration
|
|
currStillVisitedOrelTuple->DeleteIfAllowed();
|
|
currStillVisitedOrelTuple = 0;
|
|
currStillVisitedOrelTuple =
|
|
stillVisitedNodesOrelIter->GetNextTuple();
|
|
}
|
|
|
|
delete stillVisitedNodesOrelIter;
|
|
|
|
|
|
|
|
//Convert OrderedRelation to MultiMap reverseSearch
|
|
std::multimap<int, std::tuple<int, double>>
|
|
oneHopReverseMultimap;
|
|
GenericRelationIterator*
|
|
copyMultimapReverseSearchXTIter =
|
|
copyMultimapReverseSearchXT->MakeScan();
|
|
Tuple* currReverseOrelTuple =
|
|
copyMultimapReverseSearchXTIter->GetNextTuple();
|
|
|
|
while(currReverseOrelTuple)
|
|
{
|
|
CcInt* currReverseTupleIdU = (CcInt*)
|
|
currReverseOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE);
|
|
CcInt* currReverseTupleIdT = (CcInt*)
|
|
currReverseOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE);
|
|
CcReal* currReverseTupleDistUT = (CcReal*)
|
|
currReverseOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE);
|
|
|
|
std::tuple<int, double> reverseInsertMultimapTuple
|
|
= std::make_tuple(
|
|
currReverseTupleIdT->GetIntval(),
|
|
currReverseTupleDistUT->GetRealval());
|
|
//num type verwenden oder nicht?
|
|
oneHopReverseMultimap.insert(
|
|
pair<int, std::tuple<int, double>>(
|
|
currReverseTupleIdU->GetIntval(),
|
|
reverseInsertMultimapTuple));
|
|
|
|
//Free Outgoing-Iteration
|
|
currReverseOrelTuple->DeleteIfAllowed(); //TODO: ist delete ok,
|
|
// wenn zuvor einer anderen orel zugewiesen oder wird das tuple
|
|
// aus der neuen orel dann auch gelöscht?
|
|
currReverseOrelTuple = 0;
|
|
currReverseOrelTuple =
|
|
copyMultimapReverseSearchXTIter->GetNextTuple();
|
|
}
|
|
|
|
delete copyMultimapReverseSearchXTIter;
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
k->hlForwardSearchProcessIncomingEdgeIterativeSteps(
|
|
orelEdgesSource,
|
|
currNodeIdV->GetIntval(),
|
|
notYetVisitedNodesMultiMap,
|
|
stillVisitedNodesSet, oneHopReverseMultimap,
|
|
hHop->GetIntval(),
|
|
distSV->GetRealval());
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
|
|
|
|
//convert multimap back to OrderedRelation notYetVisitedNodes
|
|
notYetVisitedNodesOrel->Clear();
|
|
for (std::multimap<double, std::tuple<int, int>>::iterator
|
|
notYetVisitedNodesMultiMapIter =
|
|
notYetVisitedNodesMultiMap.begin();
|
|
notYetVisitedNodesMultiMapIter !=
|
|
notYetVisitedNodesMultiMap.end();
|
|
++notYetVisitedNodesMultiMapIter)
|
|
{
|
|
std::tuple<int, int> currTupleConvertNotYet =
|
|
(*notYetVisitedNodesMultiMapIter).second;
|
|
|
|
ListExpr relTypeNotYet;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetNotYetVisitedNodesTypeInfo(),
|
|
relTypeNotYet); //TODO: passt das? das ist ein orel type info,
|
|
// kein tuple type info
|
|
ListExpr tupNumTypeNotYet =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relTypeNotYet));
|
|
//TODO: passt das?
|
|
Tuple* notYetInsertOrelTuple = new Tuple(
|
|
tupNumTypeNotYet);
|
|
//num type verwenden oder nicht?
|
|
notYetInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_NOT_YET_VISITED,
|
|
new CcReal(true,
|
|
(*notYetVisitedNodesMultiMapIter).first));
|
|
notYetInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED
|
|
- 1>(currTupleConvertNotYet)));
|
|
notYetInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED
|
|
- 1>(currTupleConvertNotYet)));
|
|
notYetVisitedNodesOrel->AppendTuple(
|
|
notYetInsertOrelTuple);
|
|
notYetInsertOrelTuple->DeleteIfAllowed();
|
|
//TODO: warum muss der Tuple gelöscht werden? wird er per beim
|
|
// Append geklont? Nicht dass das Löschen hier den Tuple in der
|
|
// Relation zerstört.
|
|
}
|
|
|
|
|
|
|
|
//convert multimap back to OrderedRelation notYetVisitedNodes
|
|
stillVisitedNodesOrel->Clear();
|
|
for (std::unordered_set<int>::iterator
|
|
stillVisitedNodesSetIter =
|
|
stillVisitedNodesSet.begin();
|
|
stillVisitedNodesSetIter !=
|
|
stillVisitedNodesSet.end();
|
|
++stillVisitedNodesSetIter)
|
|
{
|
|
ListExpr relTypeStillVisited;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetStillVisitedNodesTypeInfo(),
|
|
relTypeStillVisited); //TODO: passt das? das ist ein orel
|
|
// type info, kein tuple type info
|
|
ListExpr tupNumTypeStillVisited =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(
|
|
relTypeStillVisited));//TODO: passt das?
|
|
Tuple* stillVisitedInsertOrelTuple = new Tuple(
|
|
tupNumTypeStillVisited);
|
|
//num type verwenden oder nicht?
|
|
stillVisitedInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_STILL_VISITED,
|
|
new CcInt(true, *stillVisitedNodesSetIter));
|
|
stillVisitedNodesOrel->AppendTuple(
|
|
stillVisitedInsertOrelTuple);
|
|
stillVisitedInsertOrelTuple->DeleteIfAllowed(); //TODO: warum muss der
|
|
// Tuple gelöscht werden? wird er per beim Append geklont?
|
|
// Nicht dass das Löschen hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
|
|
|
|
//convert multimap back to OrderedRelation notYetVisitedNodes
|
|
copyMultimapReverseSearchXT->Clear();
|
|
for (std::multimap<int, std::tuple<int, double>>::iterator
|
|
oneHopReverseMultimapIter =
|
|
oneHopReverseMultimap.begin();
|
|
oneHopReverseMultimapIter !=
|
|
oneHopReverseMultimap.end();
|
|
++oneHopReverseMultimapIter)
|
|
{
|
|
std::tuple<int, double> currTupleConvertReverse =
|
|
(*oneHopReverseMultimapIter).second;
|
|
|
|
ListExpr relTypeReverse;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetOneHopReverseOrelIdTypeInfo(),
|
|
relTypeReverse); //TODO: passt das? das ist ein orel type info,
|
|
// kein tuple type info
|
|
ListExpr tupNumTypeReverse =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relTypeReverse));
|
|
//TODO: passt das?
|
|
Tuple* reverseInsertOrelTuple = new Tuple(
|
|
tupNumTypeReverse);
|
|
//num type verwenden oder nicht?
|
|
reverseInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE,
|
|
new CcInt(true,
|
|
(*oneHopReverseMultimapIter).first));
|
|
reverseInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE
|
|
- 1>(currTupleConvertReverse)));
|
|
reverseInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE,
|
|
new CcReal(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE
|
|
- 1>(currTupleConvertReverse)));
|
|
copyMultimapReverseSearchXT->AppendTuple(
|
|
reverseInsertOrelTuple);
|
|
reverseInsertOrelTuple->DeleteIfAllowed(); //TODO: warum muss der Tuple
|
|
// gelöscht werden? wird er per beim Append geklont? Nicht dass das
|
|
// Löschen hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
//Änderungen an als Parameter übergebenen Orels persistieren
|
|
qp->SetModified(qp->GetSon(s,1));
|
|
qp->SetModified(qp->GetSon(s,2));
|
|
qp->SetModified(qp->GetSon(s,3));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlForwardSearchProcessIncomingEdgeInitialStepsVM (
|
|
Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* orelEdgesSource =
|
|
(OrderedRelation*) args[0].addr;
|
|
OrderedRelation* notYetVisitedNodesOrel =
|
|
(OrderedRelation*) args[1].addr;
|
|
OrderedRelation* copyMultimapReverseSearchXT =
|
|
(OrderedRelation*) args[2].addr;
|
|
CcInt* currNodeIdS = (CcInt*) args[3].addr;
|
|
CcInt* currNodeIdV = (CcInt*) args[4].addr;
|
|
CcReal* distSV = (CcReal*) args[5].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
CcInt* resultInt = (CcInt*)
|
|
result.addr; // cast the result
|
|
resultInt->Set(true, 1);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
|
|
//convert OrderedRelation to multimap notYetVisited
|
|
std::multimap<double, std::tuple<int, int>>
|
|
notYetVisitedNodesMultiMap;
|
|
GenericRelationIterator*
|
|
notYetVisitedOrelResultIter =
|
|
notYetVisitedNodesOrel->MakeScan();
|
|
Tuple* notYetOrelTuple =
|
|
notYetVisitedOrelResultIter->GetNextTuple();
|
|
|
|
while(notYetOrelTuple)
|
|
{
|
|
CcReal* currNotYetDist = (CcReal*)
|
|
notYetOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_NOT_YET_VISITED);
|
|
CcInt* currNotYetNodeId = (CcInt*)
|
|
notYetOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED);
|
|
CcInt* currNotYetHopDepth = (CcInt*)
|
|
notYetOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED);
|
|
|
|
std::tuple<int, int> insertMultimapTupleNotYet =
|
|
std::make_tuple(
|
|
currNotYetNodeId->GetIntval(),
|
|
currNotYetHopDepth->GetIntval());
|
|
notYetVisitedNodesMultiMap.insert(
|
|
pair<double, std::tuple<int, int>>(
|
|
currNotYetDist->GetRealval(),
|
|
insertMultimapTupleNotYet));
|
|
|
|
notYetOrelTuple->DeleteIfAllowed();
|
|
notYetOrelTuple = 0;
|
|
notYetOrelTuple =
|
|
notYetVisitedOrelResultIter->GetNextTuple();
|
|
}
|
|
|
|
//free resources
|
|
delete notYetVisitedOrelResultIter;
|
|
|
|
|
|
|
|
//Convert OrderedRelation to MultiMap reverseSearch
|
|
std::multimap<int, std::tuple<int, double>>
|
|
oneHopReverseMultimap;
|
|
GenericRelationIterator*
|
|
copyMultimapReverseSearchXTIter =
|
|
copyMultimapReverseSearchXT->MakeScan();
|
|
Tuple* currReverseOrelTuple =
|
|
copyMultimapReverseSearchXTIter->GetNextTuple();
|
|
|
|
while(currReverseOrelTuple)
|
|
{
|
|
CcInt* currReverseTupleIdU = (CcInt*)
|
|
currReverseOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE);
|
|
CcInt* currReverseTupleIdT = (CcInt*)
|
|
currReverseOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE);
|
|
CcReal* currReverseTupleDistUT = (CcReal*)
|
|
currReverseOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE);
|
|
|
|
std::tuple<int, double> reverseInsertMultimapTuple
|
|
= std::make_tuple(
|
|
currReverseTupleIdT->GetIntval(),
|
|
currReverseTupleDistUT->GetRealval());
|
|
oneHopReverseMultimap.insert(
|
|
pair<int, std::tuple<int, double>>(
|
|
currReverseTupleIdU->GetIntval(),
|
|
reverseInsertMultimapTuple));
|
|
|
|
//Free Outgoing-Iteration
|
|
currReverseOrelTuple->DeleteIfAllowed(); //TODO: ist delete ok,
|
|
// wenn zuvor einer anderen orel zugewiesen oder wird das tuple
|
|
// aus der neuen orel dann auch gelöscht?
|
|
currReverseOrelTuple = 0;
|
|
currReverseOrelTuple =
|
|
copyMultimapReverseSearchXTIter->GetNextTuple();
|
|
}
|
|
|
|
delete copyMultimapReverseSearchXTIter;
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
k->hlForwardSearchProcessIncomingEdgeInitialSteps(
|
|
orelEdgesSource,
|
|
currNodeIdV->GetIntval(), currNodeIdS,
|
|
notYetVisitedNodesMultiMap,
|
|
oneHopReverseMultimap, distSV->GetRealval());
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
|
|
|
|
//convert multimap back to OrderedRelation notYetVisitedNodes
|
|
notYetVisitedNodesOrel->Clear();
|
|
for (std::multimap<double, std::tuple<int, int>>::iterator
|
|
notYetVisitedNodesMultiMapIter =
|
|
notYetVisitedNodesMultiMap.begin();
|
|
notYetVisitedNodesMultiMapIter !=
|
|
notYetVisitedNodesMultiMap.end();
|
|
++notYetVisitedNodesMultiMapIter)
|
|
{
|
|
std::tuple<int, int> currTupleConvertNotYet =
|
|
(*notYetVisitedNodesMultiMapIter).second;
|
|
|
|
ListExpr relTypeNotYet;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetNotYetVisitedNodesTypeInfo(),
|
|
relTypeNotYet); //TODO: passt das? das ist ein orel type info,
|
|
// kein tuple type info
|
|
ListExpr tupNumTypeNotYet =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relTypeNotYet));
|
|
//TODO: passt das?
|
|
Tuple* notYetInsertOrelTuple = new Tuple(
|
|
tupNumTypeNotYet);
|
|
//num type verwenden oder nicht?
|
|
notYetInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_NOT_YET_VISITED,
|
|
new CcReal(true,
|
|
(*notYetVisitedNodesMultiMapIter).first));
|
|
notYetInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED
|
|
- 1>(currTupleConvertNotYet)));
|
|
notYetInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED
|
|
- 1>(currTupleConvertNotYet)));
|
|
notYetVisitedNodesOrel->AppendTuple(
|
|
notYetInsertOrelTuple);
|
|
notYetInsertOrelTuple->DeleteIfAllowed(); //TODO: warum muss der Tuple
|
|
// gelöscht werden? wird er per beim Append geklont? Nicht dass das
|
|
// Löschen hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
|
|
|
|
//convert multimap back to OrderedRelation notYetVisitedNodes
|
|
copyMultimapReverseSearchXT->Clear();
|
|
for (std::multimap<int, std::tuple<int, double>>::iterator
|
|
oneHopReverseMultimapIter =
|
|
oneHopReverseMultimap.begin();
|
|
oneHopReverseMultimapIter !=
|
|
oneHopReverseMultimap.end();
|
|
++oneHopReverseMultimapIter)
|
|
{
|
|
std::tuple<int, double> currTupleConvertReverse =
|
|
(*oneHopReverseMultimapIter).second;
|
|
|
|
ListExpr relTypeReverse;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetOneHopReverseOrelIdTypeInfo(),
|
|
relTypeReverse);
|
|
//TODO: passt das? das ist ein orel type info, kein tuple type info
|
|
ListExpr tupNumTypeReverse =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relTypeReverse));
|
|
//TODO: passt das?
|
|
Tuple* reverseInsertOrelTuple = new Tuple(
|
|
tupNumTypeReverse);
|
|
//num type verwenden oder nicht?
|
|
reverseInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE,
|
|
new CcInt(true,
|
|
(*oneHopReverseMultimapIter).first));
|
|
reverseInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE
|
|
- 1>(currTupleConvertReverse)));
|
|
reverseInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE,
|
|
new CcReal(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE
|
|
- 1>(currTupleConvertReverse)));
|
|
copyMultimapReverseSearchXT->AppendTuple(
|
|
reverseInsertOrelTuple);
|
|
reverseInsertOrelTuple->DeleteIfAllowed(); //TODO: warum muss der
|
|
// Tuple gelöscht werden? wird er per beim Append geklont?
|
|
// Nicht dass das Löschen hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
//Änderungen an als Parameter übergebenen Orels persistieren
|
|
qp->SetModified(qp->GetSon(s,1));
|
|
qp->SetModified(qp->GetSon(s,2));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlForwardSearchCreateAndAppendShortcutsVM (
|
|
Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* copyMultimapReverseSearchXT =
|
|
(OrderedRelation*) args[0].addr;
|
|
CcInt* currentSourceNodeFwdS = (CcInt*)
|
|
args[1].addr;
|
|
CcInt* currentVertexIdFwdV = (CcInt*)
|
|
args[2].addr;
|
|
CcReal* distSV = (CcReal*) args[3].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
OrderedRelation*
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted =
|
|
(OrderedRelation*) result.addr; // cast the result
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
|
|
//Convert OrderedRelation to MultiMap
|
|
std::multimap<int, std::tuple<int, double>>
|
|
reverseXTMultimap;
|
|
GenericRelationIterator* witnessListIter =
|
|
copyMultimapReverseSearchXT->MakeScan();
|
|
Tuple* currTuple =
|
|
witnessListIter->GetNextTuple();
|
|
while(currTuple)
|
|
{
|
|
CcInt* currTupleIdU = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE);
|
|
CcInt* currTupleIdT = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE);
|
|
CcReal* currTupleDistUT = (CcReal*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE);
|
|
|
|
std::tuple<int, double> insertTuple =
|
|
std::make_tuple(
|
|
currTupleIdT->GetIntval(),
|
|
currTupleDistUT->GetRealval());
|
|
//num type verwenden oder nicht?
|
|
reverseXTMultimap.insert(
|
|
pair<int, std::tuple<int, double>>(
|
|
currTupleIdU->GetIntval(), insertTuple));
|
|
|
|
//Free Outgoing-Iteration
|
|
currTuple->DeleteIfAllowed(); //TODO: ist delete ok, wenn zuvor
|
|
// einer anderen orel zugewiesen oder wird das tuple aus der
|
|
// neuen orel dann auch gelöscht?
|
|
currTuple = 0;
|
|
currTuple = witnessListIter->GetNextTuple();
|
|
}
|
|
|
|
delete witnessListIter;
|
|
|
|
std::multimap<int, std::tuple<int, double, int>>
|
|
shortcutsMultimap;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
k->hlForwardSearchCreateAndAppendShortcuts(
|
|
shortcutsMultimap,
|
|
reverseXTMultimap,
|
|
currentSourceNodeFwdS->GetIntval(),
|
|
currentVertexIdFwdV->GetIntval(),
|
|
distSV->GetRealval());
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
//convert multimap back to OrdeedRelation
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted->Clear();
|
|
for (std::multimap<int, std::tuple<int, double, int>>::iterator
|
|
shortcutsMultimapIter = shortcutsMultimap.begin();
|
|
shortcutsMultimapIter != shortcutsMultimap.end();
|
|
++shortcutsMultimapIter)
|
|
{
|
|
std::tuple<int, double, int> currTuple =
|
|
(*shortcutsMultimapIter).second;
|
|
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetShortcutsCreatedSourceTypeInfo(),
|
|
relType);
|
|
//TODO: passt das? das ist ein orel type info, kein tuple type info
|
|
ListExpr tupNumType =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relType));
|
|
//TODO: passt das?
|
|
Tuple* insertTuple = new Tuple(tupNumType);
|
|
//num type verwenden oder nicht?
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_SOURCE_IN_SHORTCUT_TUPLE,
|
|
new CcInt(true, (*shortcutsMultimapIter).first));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_TARGET_IN_SHORTCUT_TUPLE,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_TARGET_IN_SHORTCUT_TUPLE
|
|
- 1>(currTuple)));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_SHORTCUT_TUPLE,
|
|
new CcReal(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_SHORTCUT_TUPLE
|
|
- 1>(currTuple)));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_PARENT_ID_IN_SHORTCUT_TUPLE,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_PARENT_ID_IN_SHORTCUT_TUPLE
|
|
- 1>(currTuple)));
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted->AppendTuple(
|
|
insertTuple);
|
|
insertTuple->DeleteIfAllowed(); //TODO: warum muss der Tuple
|
|
// gelöscht werden? wird er per beim Append geklont?
|
|
// Nicht dass das Löschen hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlForwardSearchProcessIncomingEdgeVM (
|
|
Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* orelEdgesSource =
|
|
(OrderedRelation*) args[0].addr;
|
|
OrderedRelation* stillVisitedNodesOrel =
|
|
(OrderedRelation*) args[1].addr;
|
|
OrderedRelation* copyMultimapReverseSearchXT =
|
|
(OrderedRelation*) args[2].addr;
|
|
OrderedRelation*
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted =
|
|
(OrderedRelation*) args[3].addr;
|
|
CcInt* currentSourceNodeFwdS = (CcInt*)
|
|
args[4].addr;
|
|
CcInt* currentVertexIdFwdV = (CcInt*)
|
|
args[5].addr;
|
|
CcInt* hDepth = (CcInt*) args[6].addr;
|
|
CcReal* distSV = (CcReal*) args[7].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
CcInt* resultInt = (CcInt*)
|
|
result.addr; // cast the result
|
|
resultInt->Set(true, 1);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
//Convert OrderedRelation to MultiMap
|
|
std::multimap<int, std::tuple<int, double>>
|
|
oneHopReverseMultimap;
|
|
GenericRelationIterator* witnessListIter =
|
|
copyMultimapReverseSearchXT->MakeScan();
|
|
Tuple* currReverseXTOrelTuple =
|
|
witnessListIter->GetNextTuple();
|
|
while(currReverseXTOrelTuple)
|
|
{
|
|
CcInt* currTupleIdU = (CcInt*)
|
|
currReverseXTOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE);
|
|
CcInt* currTupleIdT = (CcInt*)
|
|
currReverseXTOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE);
|
|
CcReal* currTupleDistUT = (CcReal*)
|
|
currReverseXTOrelTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE);
|
|
|
|
std::tuple<int, double> insertTuple =
|
|
std::make_tuple(
|
|
currTupleIdT->GetIntval(),
|
|
currTupleDistUT->GetRealval());
|
|
//num type verwenden oder nicht?
|
|
oneHopReverseMultimap.insert(
|
|
pair<int, std::tuple<int, double>>(
|
|
currTupleIdU->GetIntval(), insertTuple));
|
|
|
|
//Free Outgoing-Iteration
|
|
currReverseXTOrelTuple->DeleteIfAllowed(); //TODO: ist delete ok,
|
|
// wenn zuvor einer anderen orel zugewiesen oder wird das tuple
|
|
// aus der neuen orel dann auch gelöscht?
|
|
currReverseXTOrelTuple = 0;
|
|
currReverseXTOrelTuple =
|
|
witnessListIter->GetNextTuple();
|
|
}
|
|
delete witnessListIter;
|
|
|
|
|
|
std::unordered_set<int> stillVisitedNodesSet;
|
|
|
|
std::multimap<int, std::tuple<int, double, int>>
|
|
shortcutsMultimap;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
k->hlForwardSearchProcessIncomingEdge(
|
|
orelEdgesSource, shortcutsMultimap,
|
|
currentVertexIdFwdV->GetIntval(),
|
|
currentSourceNodeFwdS,
|
|
stillVisitedNodesSet, oneHopReverseMultimap,
|
|
hDepth->GetIntval(),
|
|
distSV->GetRealval());
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
//convert multimap back to OrdeedRelation
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted->Clear();
|
|
for (std::multimap<int, std::tuple<int, double, int>>::iterator
|
|
shortcutsMultimapIter = shortcutsMultimap.begin();
|
|
shortcutsMultimapIter != shortcutsMultimap.end();
|
|
++shortcutsMultimapIter)
|
|
{
|
|
std::tuple<int, double, int> currTuple =
|
|
(*shortcutsMultimapIter).second;
|
|
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetShortcutsCreatedSourceTypeInfo(),
|
|
relType);
|
|
//TODO: passt das? das ist ein orel type info, kein tuple type info
|
|
ListExpr tupNumType =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relType));
|
|
//TODO: passt das?
|
|
Tuple* insertTuple = new Tuple(tupNumType);
|
|
//num type verwenden oder nicht?
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_SOURCE_IN_SHORTCUT_TUPLE,
|
|
new CcInt(true, (*shortcutsMultimapIter).first));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_TARGET_IN_SHORTCUT_TUPLE,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_TARGET_IN_SHORTCUT_TUPLE
|
|
- 1>(currTuple)));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_SHORTCUT_TUPLE,
|
|
new CcReal(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_SHORTCUT_TUPLE
|
|
- 1>(currTuple)));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_PARENT_ID_IN_SHORTCUT_TUPLE,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_PARENT_ID_IN_SHORTCUT_TUPLE
|
|
- 1>(currTuple)));
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted->AppendTuple(
|
|
insertTuple);
|
|
insertTuple->DeleteIfAllowed(); //TODO: warum muss der Tuple gelöscht
|
|
// werden? wird er per beim Append geklont? Nicht dass das Löschen
|
|
// hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
|
|
|
|
//convert multimap back to OrderedRelation notYetVisitedNodes
|
|
stillVisitedNodesOrel->Clear();
|
|
for (std::unordered_set<int>::iterator
|
|
stillVisitedNodesSetIter =
|
|
stillVisitedNodesSet.begin();
|
|
stillVisitedNodesSetIter !=
|
|
stillVisitedNodesSet.end();
|
|
++stillVisitedNodesSetIter)
|
|
{
|
|
ListExpr relTypeStillVisited;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetStillVisitedNodesTypeInfo(),
|
|
relTypeStillVisited); //TODO: passt das? das ist ein orel type info,
|
|
// kein tuple type info
|
|
ListExpr tupNumTypeStillVisited =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(
|
|
relTypeStillVisited));//TODO: passt das?
|
|
Tuple* stillVisitedInsertOrelTuple = new Tuple(
|
|
tupNumTypeStillVisited);
|
|
//num type verwenden oder nicht?
|
|
stillVisitedInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_STILL_VISITED,
|
|
new CcInt(true, *stillVisitedNodesSetIter));
|
|
stillVisitedNodesOrel->AppendTuple(
|
|
stillVisitedInsertOrelTuple);
|
|
stillVisitedInsertOrelTuple->DeleteIfAllowed();
|
|
//TODO: warum muss der Tuple gelöscht werden? wird er per beim Append
|
|
// geklont? Nicht dass das Löschen hier den Tuple in der
|
|
// Relation zerstört.
|
|
}
|
|
|
|
|
|
|
|
//convert multimap back to OrderedRelation notYetVisitedNodes
|
|
copyMultimapReverseSearchXT->Clear();
|
|
for (std::multimap<int, std::tuple<int, double>>::iterator
|
|
oneHopReverseMultimapIter =
|
|
oneHopReverseMultimap.begin();
|
|
oneHopReverseMultimapIter !=
|
|
oneHopReverseMultimap.end();
|
|
++oneHopReverseMultimapIter)
|
|
{
|
|
std::tuple<int, double> currTupleConvertReverse =
|
|
(*oneHopReverseMultimapIter).second;
|
|
|
|
ListExpr relTypeReverse;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetOneHopReverseOrelIdTypeInfo(),
|
|
relTypeReverse);
|
|
//TODO: passt das? das ist ein orel type info, kein tuple type info
|
|
ListExpr tupNumTypeReverse =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relTypeReverse));
|
|
//TODO: passt das?
|
|
Tuple* reverseInsertOrelTuple = new Tuple(
|
|
tupNumTypeReverse);
|
|
//num type verwenden oder nicht?
|
|
reverseInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_U_IN_TEMP_REV_TUPLE,
|
|
new CcInt(true,
|
|
(*oneHopReverseMultimapIter).first));
|
|
reverseInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_ID_OF_T_IN_TEMP_REV_TUPLE
|
|
- 1>(currTupleConvertReverse)));
|
|
reverseInsertOrelTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE,
|
|
new CcReal(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_TEMP_REV_TUPLE
|
|
- 1>(currTupleConvertReverse)));
|
|
copyMultimapReverseSearchXT->AppendTuple(
|
|
reverseInsertOrelTuple);
|
|
reverseInsertOrelTuple->DeleteIfAllowed(); //TODO: warum muss der
|
|
// Tuple gelöscht werden? wird er per beim Append geklont? Nicht dass
|
|
// das Löschen hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
//Änderungen an als Parameter übergebenen Orels persistieren
|
|
qp->SetModified(qp->GetSon(s,1));
|
|
qp->SetModified(qp->GetSon(s,2));
|
|
qp->SetModified(qp->GetSon(s,3));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlRemoveContractedEdgesFromEdgesRelationsVM (
|
|
Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* edgesCopyOrelSource =
|
|
(OrderedRelation*) args[0].addr;
|
|
OrderedRelation* edgesCopyOrelTarget =
|
|
(OrderedRelation*) args[1].addr;
|
|
CcInt* currentContractV = (CcInt*) args[2].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
CcInt* resultInt = (CcInt*)
|
|
result.addr; // cast the result
|
|
resultInt->Set(true, 1);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
k->hlRemoveContractedEdgesFromEdgesRelations(
|
|
edgesCopyOrelSource,
|
|
edgesCopyOrelTarget, currentContractV);
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
//Änderungen an als Parameter übergebenen Orels persistieren
|
|
qp->SetModified(qp->GetSon(s,0));
|
|
qp->SetModified(qp->GetSon(s,1));
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlRemoveParallelEdgesFromEdgesRelationsVM (
|
|
Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* edgesCopyOrelSource =
|
|
(OrderedRelation*) args[0].addr;
|
|
OrderedRelation* edgesCopyOrelTarget =
|
|
(OrderedRelation*) args[1].addr;
|
|
OrderedRelation*
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted =
|
|
(OrderedRelation*) args[2].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
CcInt* resultInt = (CcInt*)
|
|
result.addr; // cast the result
|
|
resultInt->Set(true, 1);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
|
|
|
|
//Convert OrderedRelation to MultiMap
|
|
std::multimap<int, std::tuple<int, double, int>>
|
|
shortcutsMultimap;
|
|
GenericRelationIterator*
|
|
shortcutsToBeCreatedOrelSourceToBeDeletedIter =
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted->MakeScan();
|
|
Tuple* currTuple =
|
|
shortcutsToBeCreatedOrelSourceToBeDeletedIter->GetNextTuple();
|
|
while(currTuple)
|
|
{
|
|
CcInt* currTupleIdS = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_SOURCE_IN_EDGE_TUPLE);
|
|
CcInt* currTupleIdT = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_TARGET_IN_EDGE_TUPLE);
|
|
double currTupleDistST =
|
|
0.0; //we want the shortcut to be shorter
|
|
int currTupleParentST = 999; //doesnt matter here
|
|
|
|
std::tuple<int, double, int> insertTuple =
|
|
std::make_tuple(
|
|
currTupleIdT->GetIntval(), currTupleDistST,
|
|
currTupleParentST);
|
|
//num type verwenden oder nicht?
|
|
shortcutsMultimap.insert(
|
|
pair<int, std::tuple<int, double, int>>(
|
|
currTupleIdS->GetIntval(), insertTuple));
|
|
|
|
//Free Outgoing-Iteration
|
|
currTuple->DeleteIfAllowed();
|
|
//TODO: ist delete ok, wenn zuvor einer anderen orel zugewiesen
|
|
// oder wird das tuple aus der neuen orel dann auch gelöscht?
|
|
currTuple = 0;
|
|
currTuple =
|
|
shortcutsToBeCreatedOrelSourceToBeDeletedIter->GetNextTuple();
|
|
}
|
|
delete shortcutsToBeCreatedOrelSourceToBeDeletedIter;
|
|
|
|
|
|
k->hlRemoveParallelEdgesFromEdgesRelations(
|
|
edgesCopyOrelSource,
|
|
edgesCopyOrelTarget, shortcutsMultimap);
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
//Änderungen an als Parameter übergebenen Orels persistieren
|
|
qp->SetModified(qp->GetSon(s,0));
|
|
qp->SetModified(qp->GetSon(s,1));
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlDoContractionVM (Word* args, Word& result,
|
|
int message, Word& local,
|
|
Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* edgesWithViaOrelSource =
|
|
(OrderedRelation*) args[0].addr;
|
|
OrderedRelation* edgesWithViaOrelTarget =
|
|
(OrderedRelation*) args[1].addr;
|
|
CcInt* currentVToBeContracted = (CcInt*)
|
|
args[2].addr;
|
|
CcInt* hHop = (CcInt*) args[3].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
OrderedRelation*
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted =
|
|
(OrderedRelation*) result.addr; // cast the result
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
std::multimap<int, std::tuple<int, double, int>>
|
|
shortcutsMultimap;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
k->hlDoContraction(edgesWithViaOrelSource,
|
|
edgesWithViaOrelTarget,
|
|
shortcutsMultimap, currentVToBeContracted,
|
|
hHop->GetIntval());
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
//convert multimap back to OrderedRelation
|
|
for (std::multimap<int, std::tuple<int, double, int>>::iterator
|
|
shortcutsMultimapIter = shortcutsMultimap.begin();
|
|
shortcutsMultimapIter != shortcutsMultimap.end();
|
|
++shortcutsMultimapIter)
|
|
{
|
|
std::tuple<int, double, int> currTuple =
|
|
(*shortcutsMultimapIter).second;
|
|
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetShortcutsCreatedSourceTypeInfo(),
|
|
relType);
|
|
//TODO: passt das? das ist ein orel type info, kein tuple type info
|
|
ListExpr tupNumType =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relType));
|
|
//TODO: passt das?
|
|
Tuple* insertTuple = new Tuple(tupNumType);
|
|
//num type verwenden oder nicht?
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_SOURCE_IN_SHORTCUT_TUPLE,
|
|
new CcInt(true, (*shortcutsMultimapIter).first));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_TARGET_IN_SHORTCUT_TUPLE,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_TARGET_IN_SHORTCUT_TUPLE
|
|
- 1>(currTuple)));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_SHORTCUT_TUPLE,
|
|
new CcReal(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_SHORTCUT_TUPLE
|
|
- 1>(currTuple)));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_PARENT_ID_IN_SHORTCUT_TUPLE,
|
|
new CcInt(true,
|
|
std::get<HubLabelClass::HL_INDEX_OF_PARENT_ID_IN_SHORTCUT_TUPLE
|
|
- 1>(currTuple)));
|
|
shortcutsToBeCreatedOrelSourceToBeDeleted->AppendTuple(
|
|
insertTuple);
|
|
insertTuple->DeleteIfAllowed(); //TODO: warum muss der Tuple gelöscht
|
|
// werden? wird er per beim Append geklont? Nicht dass das Löschen
|
|
// hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
//Änderungen an als Parameter übergebenen Orels persistieren
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlIterateOverAllNodesByRankAscAndDoContractionVM (
|
|
Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* nodesWithRankOrelRank =
|
|
(OrderedRelation*) args[0].addr;
|
|
OrderedRelation* edgesWithViaOrelSource =
|
|
(OrderedRelation*) args[1].addr;
|
|
OrderedRelation* edgesWithViaOrelTarget =
|
|
(OrderedRelation*) args[2].addr;
|
|
CcInt* hHop = (CcInt*) args[3].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
CcInt* resultInt = (CcInt*)
|
|
result.addr; // cast the result
|
|
resultInt->Set(true, 1);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
k->hlIterateOverAllNodesByRankAscAndDoContraction(
|
|
nodesWithRankOrelRank,
|
|
edgesWithViaOrelSource, edgesWithViaOrelTarget,
|
|
hHop->GetIntval());
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
//Änderungen an als Parameter übergebenen Orels persistieren
|
|
qp->SetModified(qp->GetSon(s,1));
|
|
qp->SetModified(qp->GetSon(s,2));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlCreateLabelCheckForWitnessScanNewVerticesVM (
|
|
Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* edgesContractedUpwardsOrelSource
|
|
=
|
|
(OrderedRelation*) args[0].addr;
|
|
OrderedRelation*
|
|
edgesContractedDownwardsOrelTarget =
|
|
(OrderedRelation*) args[1].addr;
|
|
CcInt* revGivenTargetIdV = (CcInt*) args[2].addr;
|
|
CcInt* revGivenHopDepthV = (CcInt*) args[3].addr;
|
|
CcReal* revGivenDistanceVToW = (CcReal*)
|
|
args[4].addr;
|
|
CcBool* isForward = (CcBool*) args[5].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
OrderedRelation* reverseNotYetVisitedNodesOrel =
|
|
(OrderedRelation*)
|
|
result.addr; // cast the result
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
std::vector<int> stillVisitedNodes;
|
|
stillVisitedNodes.push_back(
|
|
revGivenTargetIdV->GetIntval());
|
|
|
|
std::multimap<double, std::tuple<int, int>>
|
|
reverseNotYetVisitedNodes;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
k->hlCreateLabelCheckForWitnessScanNewVertices(
|
|
reverseNotYetVisitedNodes,
|
|
stillVisitedNodes,
|
|
edgesContractedUpwardsOrelSource,
|
|
edgesContractedDownwardsOrelTarget,
|
|
revGivenTargetIdV,
|
|
revGivenDistanceVToW->GetRealval(),
|
|
revGivenHopDepthV->GetIntval(),
|
|
isForward->GetBoolval());
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
//convert multimap back to OrderedRelation
|
|
for (std::multimap<double, std::tuple<int, int>>::iterator
|
|
reverseNotYetVisitedNodesIter =
|
|
reverseNotYetVisitedNodes.begin();
|
|
reverseNotYetVisitedNodesIter !=
|
|
reverseNotYetVisitedNodes.end();
|
|
++reverseNotYetVisitedNodesIter)
|
|
{
|
|
std::tuple<int, int> currTuple =
|
|
(*reverseNotYetVisitedNodesIter).second;
|
|
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetNotYetVisitedNodesTypeInfo(),
|
|
relType);
|
|
//TODO: passt das? das ist ein orel type info, kein tuple type info
|
|
ListExpr tupNumType =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relType));
|
|
//TODO: passt das?
|
|
Tuple* insertTuple = new Tuple(tupNumType);
|
|
//num type verwenden oder nicht?
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_NOT_YET_VISITED,
|
|
new CcReal(true,
|
|
(*reverseNotYetVisitedNodesIter).first));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED
|
|
- 1>(currTuple)));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED
|
|
- 1>(currTuple)));
|
|
reverseNotYetVisitedNodesOrel->AppendTuple(
|
|
insertTuple);
|
|
insertTuple->DeleteIfAllowed(); //TODO: warum muss der Tuple gelöscht
|
|
// werden? wird er per beim Append geklont? Nicht dass das Löschen
|
|
// hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlCreateLabelCheckForWitnessVM (Word* args,
|
|
Word& result, int message,
|
|
Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* edgesContractedUpwardsOrelSource
|
|
= (OrderedRelation*)
|
|
args[0].addr;
|
|
OrderedRelation*
|
|
edgesContractedDownwardsOrelTarget =
|
|
(OrderedRelation*)
|
|
args[1].addr;
|
|
Relation* fwdOrRvsLabelRelation = (Relation*)
|
|
args[2].addr;
|
|
CcInt* givenTargetIdW = (CcInt*) args[3].addr;
|
|
CcInt* hHopSize = (CcInt*) args[4].addr;
|
|
CcReal* givenDistanceSW = (CcReal*) args[5].addr;
|
|
CcBool* isForward = (CcBool*) args[6].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
CcInt* resultInt = (CcInt*)
|
|
result.addr; // cast the result
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result vorbereitet" << endl);
|
|
#endif
|
|
|
|
|
|
//Convert Relation to MultiMap
|
|
std::multimap<int, std::tuple<int, int, double>>
|
|
fwdOrRvsLabelMultimap;
|
|
GenericRelationIterator* fwdOrRvsLabelIter =
|
|
fwdOrRvsLabelRelation->MakeScan();
|
|
Tuple* currTuple =
|
|
fwdOrRvsLabelIter->GetNextTuple();
|
|
while(currTuple)
|
|
{
|
|
CcInt* currTupleHubIdNew = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_NODE_ID_NEW_IN_LABEL_TUPLE);
|
|
CcInt* currTupleHubID = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE);
|
|
CcInt* currTupleHubParentId = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_PARENT_NODE_ID_IN_LABEL_TUPLE);
|
|
//CcInt* currTupleHubParentTupleId = (CcInt*)
|
|
// currTuple->GetAttribute(
|
|
// HubLabelClass::HL_INDEX_OF_HUB_PARENT_TUPLE_ID_IN_LABEL_TUPLE);
|
|
//wird hier nicht benötigt
|
|
CcReal* currTupleHubDistanceToSource = (CcReal*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_DISTANCE_TO_SOURCE_IN_LABEL_TUPLE);
|
|
|
|
std::tuple<int, int, double> insertTuple =
|
|
std::make_tuple(
|
|
currTupleHubIdNew->GetIntval(),
|
|
currTupleHubParentId->GetIntval(),
|
|
currTupleHubDistanceToSource->GetRealval());
|
|
fwdOrRvsLabelMultimap.insert(
|
|
pair<int, std::tuple<int, int, double>>(
|
|
currTupleHubID->GetIntval(), insertTuple));
|
|
|
|
//Free Outgoing-Iteration
|
|
currTuple->DeleteIfAllowed(); //TODO: ist delete ok, wenn zuvor
|
|
// einer anderen orel zugewiesen oder wird das tuple aus der
|
|
// neuen orel dann auch gelöscht?
|
|
currTuple = 0;
|
|
currTuple = fwdOrRvsLabelIter->GetNextTuple();
|
|
}
|
|
delete fwdOrRvsLabelIter;
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
bool isPruned = k->hlCreateLabelCheckForWitness(
|
|
fwdOrRvsLabelMultimap,
|
|
edgesContractedUpwardsOrelSource,
|
|
edgesContractedDownwardsOrelTarget,
|
|
givenTargetIdW, givenDistanceSW->GetRealval(),
|
|
hHopSize->GetIntval(),
|
|
isForward->GetBoolval());
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
|
|
resultInt->Set(true, isPruned);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result vorbereitet" << endl);
|
|
#endif
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlCreateLabelScanNewVerticesVM (Word* args,
|
|
Word& result, int message,
|
|
Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* edgesContractedUpwardsOrelSource
|
|
= (OrderedRelation*)
|
|
args[0].addr;
|
|
OrderedRelation*
|
|
edgesContractedDownwardsOrelTarget =
|
|
(OrderedRelation*)
|
|
args[1].addr;
|
|
Relation* fwdOrRvsLabelRelation = (Relation*)
|
|
args[2].addr;
|
|
CcInt* givenTargetIdV = (CcInt*) args[3].addr;
|
|
CcReal* givenDistanceSV = (CcReal*) args[4].addr;
|
|
CcBool* isForward = (CcBool*) args[5].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
OrderedRelation* reverseNotYetVisitedNodesOrel =
|
|
(OrderedRelation*)
|
|
result.addr; // cast the result
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
|
|
|
|
std::multimap<double, std::tuple<int, int>>
|
|
labelNotYetVisitedNodes;
|
|
|
|
//Convert Relation to MultiMap and notYetMulimap
|
|
std::multimap<int, std::tuple<int, int, double>>
|
|
fwdOrRvsLabelMultimap;
|
|
std::vector<int> stillVisitedNodes;
|
|
|
|
GenericRelationIterator* fwdOrRvsLabelIter =
|
|
fwdOrRvsLabelRelation->MakeScan();
|
|
Tuple* currTuple =
|
|
fwdOrRvsLabelIter->GetNextTuple();
|
|
while(currTuple)
|
|
{
|
|
CcInt* currTupleHubID = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE);
|
|
/*
|
|
CcInt* currTupleHubIdNew = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_NODE_ID_NEW_IN_LABEL_TUPLE);
|
|
CcInt* currTupleHubParentId = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_PARENT_NODE_ID_IN_LABEL_TUPLE);
|
|
CcInt* currTupleHubParentTuplId = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_PARENT_TUPLE_ID_IN_LABEL_TUPLE);
|
|
CcReal* currTupleHubDistanceToSource = (CcReal*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_DISTANCE_TO_SOURCE_IN_LABEL_TUPLE);
|
|
|
|
std::tuple<int, int, double> insertTupleLabel =
|
|
std::make_tuple(currTupleHubIdNew->GetIntval(),
|
|
currTupleHubParentId->GetIntval(),
|
|
currTupleHubDistanceToSource->GetRealval());
|
|
*/
|
|
stillVisitedNodes.push_back(
|
|
currTupleHubID->GetIntval());
|
|
|
|
//Free Outgoing-Iteration
|
|
currTuple->DeleteIfAllowed();
|
|
currTuple = 0;
|
|
currTuple = fwdOrRvsLabelIter->GetNextTuple();
|
|
}
|
|
delete fwdOrRvsLabelIter;
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
k->hlCreateLabelScanNewVertices(
|
|
labelNotYetVisitedNodes, stillVisitedNodes,
|
|
edgesContractedUpwardsOrelSource,
|
|
edgesContractedDownwardsOrelTarget,
|
|
givenTargetIdV, givenDistanceSV->GetRealval(),
|
|
isForward->GetBoolval());
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
|
|
//convert multimap back to OrderedRelation
|
|
for (std::multimap<double, std::tuple<int, int>>::iterator
|
|
labelNotYetVisitedNodesIter =
|
|
labelNotYetVisitedNodes.begin();
|
|
labelNotYetVisitedNodesIter !=
|
|
labelNotYetVisitedNodes.end();
|
|
++labelNotYetVisitedNodesIter)
|
|
{
|
|
std::tuple<int, int> currTuple =
|
|
(*labelNotYetVisitedNodesIter).second;
|
|
|
|
ListExpr relType;
|
|
nl->ReadFromString(
|
|
HubLabelClass::hlGetNotYetVisitedNodesTypeInfo(),
|
|
relType);
|
|
//TODO: passt das? das ist ein orel type info, kein tuple type info
|
|
ListExpr tupNumType =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relType));
|
|
//TODO: passt das?
|
|
Tuple* insertTuple = new Tuple(tupNumType);
|
|
//num type verwenden oder nicht?
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_DIST_IN_NOT_YET_VISITED,
|
|
new CcReal(true,
|
|
(*labelNotYetVisitedNodesIter).first));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_NOT_YET_VISITED
|
|
- 1>(currTuple)));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_HOP_DEPTH_IN_NOT_YET_VISITED
|
|
- 1>(currTuple)));
|
|
reverseNotYetVisitedNodesOrel->AppendTuple(
|
|
insertTuple);
|
|
insertTuple->DeleteIfAllowed(); //TODO: warum muss der Tuple gelöscht
|
|
// werden? wird er per beim Append geklont? Nicht dass das Löschen
|
|
// hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlGetRankByIdVM (Word* args, Word& result,
|
|
int message, Word& local,
|
|
Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
BTree* bTreeNodesRanked = (BTree*) args[0].addr;
|
|
OrderedRelation* nodesRanked = (OrderedRelation*)
|
|
args[1].addr;
|
|
CcInt* givenNodeId = (CcInt*) args[2].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
CcInt* resultInt = (CcInt*)
|
|
result.addr; // cast the result
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
int retVal = -2;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
retVal = k->hlGetRankById(bTreeNodesRanked,
|
|
nodesRanked, givenNodeId);
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
resultInt->Set(true, retVal);
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlCreateLabelByDijkstraWithStallingVM (
|
|
Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
BTree* bTreeNodesRanked = (BTree*) args[0].addr;
|
|
OrderedRelation* nodesRanked = (OrderedRelation*)
|
|
args[1].addr;
|
|
OrderedRelation* edgesWithViaOrelSource =
|
|
(OrderedRelation*) args[2].addr;
|
|
OrderedRelation* edgesWithViaOrelTarget =
|
|
(OrderedRelation*) args[3].addr;
|
|
CcInt* sourceNodeId = (CcInt*) args[4].addr;
|
|
CcInt* hHop = (CcInt*) args[5].addr;
|
|
CcBool* isForward = (CcBool*) args[6].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
Relation* fwdOrRvsLabelRel = (Relation*)
|
|
result.addr; // cast the result
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
|
|
std::multimap<int, std::tuple<int, int, double>>
|
|
fwdOrRvsLabelMultimap;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
k->hlCreateLabelByDijkstraWithStalling(
|
|
bTreeNodesRanked, nodesRanked,
|
|
edgesWithViaOrelSource, edgesWithViaOrelTarget,
|
|
fwdOrRvsLabelMultimap,
|
|
sourceNodeId, hHop->GetIntval(),
|
|
isForward->GetBoolval());
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
|
|
//convert multimap back to OrderedRelation
|
|
for (std::multimap<int, std::tuple<int, int, double>>::iterator
|
|
fwdOrRvsLabelMultimapIter =
|
|
fwdOrRvsLabelMultimap.begin();
|
|
fwdOrRvsLabelMultimapIter !=
|
|
fwdOrRvsLabelMultimap.end();
|
|
++fwdOrRvsLabelMultimapIter)
|
|
{
|
|
std::tuple<int, int, double> currTuple =
|
|
(*fwdOrRvsLabelMultimapIter).second;
|
|
|
|
TupleType* tupleType =
|
|
fwdOrRvsLabelRel->GetTupleType();
|
|
//TODO: nicht löschen oder doch?
|
|
Tuple* insertTuple = new Tuple(
|
|
tupleType);//TODO: num type
|
|
// verwenden oder nicht?
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_NODE_ID_NEW_IN_LABEL_TUPLE,
|
|
new CcInt(true,
|
|
(*fwdOrRvsLabelMultimapIter).first));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE
|
|
- 1>(currTuple)));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_PARENT_NODE_ID_IN_LABEL_TUPLE,
|
|
new CcInt(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_HUB_PARENT_NODE_ID_IN_LABEL_TUPLE
|
|
- 1>(currTuple)));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_PARENT_TUPLE_ID_IN_LABEL_TUPLE,
|
|
new CcInt(true, -1));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_DISTANCE_TO_SOURCE_IN_LABEL_TUPLE,
|
|
new CcReal(true, std::get<
|
|
HubLabelClass::HL_INDEX_OF_HUB_DISTANCE_TO_SOURCE_IN_LABEL_TUPLE
|
|
- 2>(currTuple)));
|
|
//its -2 here because the multimap does not
|
|
// contain the hubTupleId usually on indexposition #3
|
|
fwdOrRvsLabelRel->AppendTuple(insertTuple);
|
|
insertTuple->DeleteIfAllowed(); //TODO: warum muss der Tuple gelöscht
|
|
// werden? wird er per beim Append geklont? Nicht dass
|
|
// das Löschen hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int hlFillForwardOrReverseLabelVM (Word* args,
|
|
Word& result, int message,
|
|
Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
Relation* fwdOrRvsLabelRelation = (Relation*)
|
|
args[0].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
NestedRelation* allLabelsNrel = (NestedRelation*)
|
|
result.addr;
|
|
// cast the result
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
|
|
std::multimap<int, std::tuple<int, int, double>>
|
|
labelfwdOrRvsMultimap;
|
|
|
|
int rootNodeId = -1;
|
|
|
|
GenericRelationIterator* fwdOrRvsLabelIter =
|
|
fwdOrRvsLabelRelation->MakeScan();
|
|
Tuple* currTuple =
|
|
fwdOrRvsLabelIter->GetNextTuple();
|
|
while(currTuple)
|
|
{
|
|
CcInt* currTupleHubIdNew = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_NODE_ID_NEW_IN_LABEL_TUPLE);
|
|
CcInt* currTupleHubID = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE);
|
|
CcInt* currTupleHubParentId = (CcInt*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_PARENT_NODE_ID_IN_LABEL_TUPLE);
|
|
CcReal* currTupleHubDistanceToSource = (CcReal*)
|
|
currTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_DISTANCE_TO_SOURCE_IN_LABEL_TUPLE);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("fill Label nex tuple with rank: " <<
|
|
currTupleHubIdNew->GetIntval() << " id: " <<
|
|
currTupleHubID->GetIntval() << " parentId: " <<
|
|
currTupleHubParentId->GetIntval() << endl);
|
|
#endif
|
|
std::tuple<int, int, double> insertTupleLabel =
|
|
std::make_tuple(
|
|
currTupleHubID->GetIntval(),
|
|
currTupleHubParentId->GetIntval(),
|
|
currTupleHubDistanceToSource->GetRealval());
|
|
|
|
labelfwdOrRvsMultimap.insert(
|
|
pair<int, std::tuple<int, int, double>>(
|
|
currTupleHubIdNew->GetIntval(),
|
|
insertTupleLabel));
|
|
|
|
//getRootNodeId
|
|
if(currTupleHubParentId->GetIntval() == -1)
|
|
{
|
|
rootNodeId = currTupleHubID->GetIntval();
|
|
}
|
|
//Free Outgoing-Iteration
|
|
currTuple->DeleteIfAllowed();
|
|
currTuple = 0;
|
|
currTuple = fwdOrRvsLabelIter->GetNextTuple();
|
|
}
|
|
delete fwdOrRvsLabelIter;
|
|
|
|
|
|
SubRelation* fwdOrRvsDataSubRel =
|
|
allLabelsNrel->getSubRel(
|
|
HubLabelClass::hlForwardLabelColumnName());
|
|
Relation* fwdOrRvsDataRel =
|
|
fwdOrRvsDataSubRel->rel;
|
|
|
|
SmiFileId fileId = fwdOrRvsDataSubRel->fileId;
|
|
ListExpr typeInfo = fwdOrRvsDataSubRel->typeInfo;
|
|
AttributeRelation* labelfwdOrRvsArel = new
|
|
AttributeRelation(fileId,
|
|
typeInfo);
|
|
labelfwdOrRvsArel->setPartOfNrel(true);
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
|
|
k->hlFillForwardOrReverseLabel(labelfwdOrRvsArel,
|
|
fwdOrRvsDataRel,
|
|
labelfwdOrRvsMultimap);
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
//leere zweite Arel erzeugen
|
|
SubRelation* fwdOrRvsDataSubRel2 =
|
|
allLabelsNrel->getSubRel(
|
|
HubLabelClass::hlReverseLabelColumnName());
|
|
|
|
SmiFileId fileId2 = fwdOrRvsDataSubRel2->fileId;
|
|
ListExpr typeInfo2 =
|
|
fwdOrRvsDataSubRel2->typeInfo;
|
|
AttributeRelation* labelfwdOrRvsArel2 = new
|
|
AttributeRelation(fileId2,
|
|
typeInfo2);
|
|
labelfwdOrRvsArel2->setPartOfNrel(true);
|
|
|
|
TupleType* tupleNumTypeAllLabels =
|
|
allLabelsNrel->getPrimary()->GetTupleType();
|
|
Tuple* allLabelsTuple = new Tuple(
|
|
tupleNumTypeAllLabels);
|
|
allLabelsTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_NODE_ID_IN_ALL_LABELS_TUPLE,
|
|
new CcInt(true, rootNodeId));
|
|
allLabelsTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_FORWARD_LABEL_IN_ALL_LABELS_TUPLE,
|
|
labelfwdOrRvsArel);
|
|
allLabelsTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_REVERSE_LABEL_IN_ALL_LABELS_TUPLE,
|
|
labelfwdOrRvsArel2);
|
|
|
|
allLabelsNrel->getPrimary()->AppendTuple(
|
|
allLabelsTuple);
|
|
|
|
allLabelsTuple->DeleteIfAllowed();
|
|
allLabelsTuple = 0;
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int hlGetPathViaPointsVM (Word* args,
|
|
Word& result, int message,
|
|
Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
NestedRelation* allLabelsNRel = (NestedRelation*)
|
|
args[0].addr;
|
|
BTree* allLabelsBTree = (BTree*) args[1].addr;
|
|
OrderedRelation* edgesWithShortcutsOrelSource =
|
|
(OrderedRelation*)
|
|
args[2].addr;
|
|
CcInt* rootNodeId = (CcInt*) args[3].addr;
|
|
CcInt* hubId = (CcInt*) args[4].addr;
|
|
CcBool* isForward = (CcBool*) args[5].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
Relation* shortesPath = (Relation*)
|
|
result.addr; // cast the result
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
BTreeIterator* bTreeSourceIter =
|
|
allLabelsBTree->ExactMatch(rootNodeId);
|
|
|
|
int tupleIdSource = -1;
|
|
if(bTreeSourceIter->Next())
|
|
{
|
|
tupleIdSource = bTreeSourceIter->GetId();
|
|
#ifdef USEDEBUG
|
|
LogDebug("id: " << tupleIdSource << endl);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
TupleId currTupleId = (TupleId) tupleIdSource;
|
|
Relation* primary = allLabelsNRel->getPrimary();
|
|
Tuple* currTuple = primary->GetTuple(currTupleId,
|
|
false);
|
|
int arelIndex = -1;
|
|
string columnNameArel = "";
|
|
if(isForward->GetBoolval())
|
|
{
|
|
arelIndex =
|
|
HubLabelClass::HL_INDEX_OF_FORWARD_LABEL_IN_ALL_LABELS_TUPLE;
|
|
columnNameArel =
|
|
HubLabelClass::hlForwardLabelColumnName();
|
|
}
|
|
else
|
|
{
|
|
arelIndex =
|
|
HubLabelClass::HL_INDEX_OF_REVERSE_LABEL_IN_ALL_LABELS_TUPLE;
|
|
columnNameArel =
|
|
HubLabelClass::hlReverseLabelColumnName();
|
|
}
|
|
AttributeRelation* currAttrRel =
|
|
(AttributeRelation*)
|
|
currTuple->GetAttribute(arelIndex);
|
|
SubRelation* dataSubRel =
|
|
allLabelsNRel->getSubRel(columnNameArel);
|
|
Relation* dataRel = dataSubRel->rel;
|
|
|
|
DbArray<TupleId>* tupleIds =
|
|
currAttrRel->getTupleIds();
|
|
TupleId tid;
|
|
Tuple* currDataTuple=0;
|
|
for(int i = 0; i < tupleIds->Size(); i++)
|
|
{
|
|
tupleIds->Get(i, tid);
|
|
#ifdef USEDEBUG
|
|
LogDebug("next TupleId: " << tid << endl);
|
|
#endif
|
|
Tuple* tmpCurrDataTuple = dataRel->GetTuple(tid,
|
|
false);
|
|
|
|
if(tmpCurrDataTuple)
|
|
{
|
|
CcInt* currDataTupleHubId = (CcInt*)
|
|
tmpCurrDataTuple->GetAttribute(
|
|
HubLabelClass::HL_INDEX_OF_HUB_NODE_ID_IN_LABEL_TUPLE);
|
|
#ifdef USEDEBUG
|
|
LogDebug("currNodeId: " <<
|
|
currDataTupleHubId->GetIntval() <<
|
|
" searchedHubId: " << hubId->GetIntval()<< endl);
|
|
#endif
|
|
if(hubId->GetIntval() ==
|
|
currDataTupleHubId->GetIntval())
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Tuple found for given hubId, break loop and hold"
|
|
" current Tuple object" << endl);
|
|
#endif
|
|
currDataTuple = tmpCurrDataTuple;
|
|
break;
|
|
}
|
|
}
|
|
//mpCurrDataTuple->DeleteIfAllowed(); //XXTODO darf das?
|
|
}
|
|
tupleIds->destroyIfNonPersistent(); //XXTODO: richig so?
|
|
|
|
if(!currDataTuple)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("Warnung: kein Tuple in Arel gefunden, breche ab"
|
|
<< endl);
|
|
#endif
|
|
delete k;
|
|
currTuple->DeleteIfAllowed();
|
|
return 0;
|
|
}
|
|
|
|
|
|
std::vector<Tuple*> shortestPathVector;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
k->hlGetPathViaPoints( edgesWithShortcutsOrelSource, dataRel,
|
|
currDataTuple, shortestPathVector, isForward->GetBoolval());
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
|
|
//convert multimap back to OrderedRelation
|
|
for (std::vector<Tuple*>::iterator shortesPathIter
|
|
=
|
|
shortestPathVector.begin();
|
|
shortesPathIter != shortestPathVector.end();
|
|
++shortesPathIter)
|
|
{
|
|
Tuple* currInsertTuple = *(shortesPathIter);
|
|
|
|
shortesPath->AppendTuple(currInsertTuple);
|
|
currInsertTuple->DeleteIfAllowed(); //TODO: warum muss der Tuple
|
|
// gelöscht werden? wird er per beim Append geklont? Nicht dass das
|
|
// Löschen hier den Tuple in der Relation zerstört.
|
|
}
|
|
|
|
//free resources
|
|
delete k;
|
|
currTuple->DeleteIfAllowed();
|
|
//currHub->DeleteIfAllowed(); //wird bereits in er Methode gelöscht
|
|
//XXTODO: was alles löschen hier?
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int hlQueryVM (Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
#ifdef USEPERF
|
|
double perfTime = k->getCurrentTimeInMs();
|
|
double perfTime2 = 0.0;
|
|
#endif
|
|
|
|
NestedRelation* allLabelsNRel = (NestedRelation*) args[0].addr;
|
|
BTree* allLabelsBTree = (BTree*) args[1].addr;
|
|
OrderedRelation* edgesWithShortcutsOrelSource =
|
|
(OrderedRelation*) args[2].addr;
|
|
OrderedRelation* hlGraphOrel = (OrderedRelation*) args[3].addr;
|
|
CcInt* sourceNodeId = (CcInt*) args[4].addr;
|
|
CcInt* targetNodeId = (CcInt*) args[5].addr;
|
|
CcBool* isHlGraph = (CcBool*) args[6].addr;
|
|
|
|
if(isHlGraph->GetBoolval() && !hlGraphOrel)
|
|
{
|
|
LogError(
|
|
"Fehlerhafte Parameter: isHlGraph == true but hlGraphOrel is null"
|
|
<< endl);
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(s); // use the result storage
|
|
Relation* shortesPath = (Relation*) result.addr; // cast the result
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
|
|
k->hlQuery(allLabelsNRel, allLabelsBTree, edgesWithShortcutsOrelSource,
|
|
hlGraphOrel, shortesPath, sourceNodeId, targetNodeId,
|
|
isHlGraph->GetBoolval());
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
#ifdef USEPERF
|
|
perfTime2 = k->getCurrentTimeInMs();
|
|
LogPerf("perf: duration of full hl search: (ms) "
|
|
<< fixed << (perfTime2 - perfTime)<< endl);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//XXTODO
|
|
int hlPruneLabelByBootstrappingVM (Word* args,
|
|
Word& result, int message,
|
|
Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
/*
|
|
OrderedRelation* nodesWithRankOrelRank = (OrderedRelation*) args[0].addr;
|
|
OrderedRelation* edgesWithViaOrelSource = (OrderedRelation*) args[1].addr;
|
|
OrderedRelation* edgesWithViaOrelTarget = (OrderedRelation*) args[2].addr;
|
|
CcInt* hHop = (CcInt*) args[3].addr;
|
|
CcInt* calcFunction = (CcInt*) args[4].addr;
|
|
*/
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
CcInt* resultInt = (CcInt*)
|
|
result.addr; // cast the result
|
|
resultInt->Set(true, 1);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
//k->hlPruneLabelByBootstrapping(hHop);
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
//Änderungen an als Parameter übergebenen Orels persistieren
|
|
qp->SetModified(qp->GetSon(s,1));
|
|
qp->SetModified(qp->GetSon(s,2));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//XXTODO
|
|
int hlReorderLabelsVM (Word* args, Word& result,
|
|
int message, Word& local
|
|
, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
/*
|
|
OrderedRelation* nodesWithRankOrelRank = (OrderedRelation*) args[0].addr;
|
|
OrderedRelation* edgesWithViaOrelSource = (OrderedRelation*) args[1].addr;
|
|
OrderedRelation* edgesWithViaOrelTarget = (OrderedRelation*) args[2].addr;
|
|
CcInt* hHop = (CcInt*) args[3].addr;
|
|
CcInt* calcFunction = (CcInt*) args[4].addr;
|
|
*/
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
CcInt* resultInt = (CcInt*)
|
|
result.addr; // cast the result
|
|
resultInt->Set(true, 1);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
//k->hlReorderLabels(hHop);
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
//Änderungen an als Parameter übergebenen Orels persistieren
|
|
qp->SetModified(qp->GetSon(s,1));
|
|
qp->SetModified(qp->GetSon(s,2));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//XXTODO
|
|
int hlCreateLabelsVM (Word* args, Word& result,
|
|
int message, Word& local,
|
|
Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start" << endl);
|
|
#endif
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
BTree* bTreeNodesWithRankOrelRank =
|
|
(BTree*) args[0].addr;
|
|
OrderedRelation* nodesWithRankOrelRank =
|
|
(OrderedRelation*) args[1].addr;
|
|
OrderedRelation* edgesWithViaOrelSource =
|
|
(OrderedRelation*) args[2].addr;
|
|
OrderedRelation* edgesWithViaOrelTarget =
|
|
(OrderedRelation*) args[3].addr;
|
|
CcInt* hHop = (CcInt*) args[4].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(
|
|
s); // use the result storage
|
|
NestedRelation* allLabelsNrel = (NestedRelation*)
|
|
result.addr;
|
|
// cast the result
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
k->hlCreateLabels(allLabelsNrel,
|
|
bTreeNodesWithRankOrelRank,
|
|
nodesWithRankOrelRank, edgesWithViaOrelSource,
|
|
edgesWithViaOrelTarget,
|
|
hHop->GetIntval());
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
5.2.2 Value Mappings of (2) In-Memory Approach
|
|
|
|
*/
|
|
|
|
|
|
/*
|
|
Takes an OSM-Graph (Orel Edges) and creates an HlGraph.
|
|
Retrieves an Orel-Representation of that graph.
|
|
Only used for testing purposes.
|
|
|
|
|
|
*/
|
|
int hlTransformOrelToHlGraphVM (Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlTransformOrelToHlGraphVM" << endl);
|
|
#endif
|
|
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* edgesOrelSource = (OrderedRelation*) args[0].addr;
|
|
OrderedRelation* nodesOrel = (OrderedRelation*) args[1].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(s); // use the result storage
|
|
OrderedRelation* reTransformedGraphOrel =
|
|
(OrderedRelation*) result.addr; // cast the result
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
//initialize vector with number of nodes
|
|
// such that we can use []-operator of vector instead using push_back
|
|
std::vector<HlNodeEntry*> nodesEdgesVector(nodesOrel->GetNoTuples());
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
k->hlTransformOrelToHlGraph(nodesOrel, edgesOrelSource, nodesEdgesVector);
|
|
#ifdef USEDEBUG
|
|
LogDebug("fertig" << endl);
|
|
#endif
|
|
|
|
|
|
//convert multimap back to OrderedRelation
|
|
for (uint currSourceNodeIndex = 0;
|
|
currSourceNodeIndex < nodesEdgesVector.size();
|
|
currSourceNodeIndex++)
|
|
{
|
|
HlNodeEntry* currNodeEntry = nodesEdgesVector[currSourceNodeIndex];
|
|
int currSourceNodeId = currNodeEntry->getNodeId();
|
|
int currNodeRank = currNodeEntry->getRankValue();
|
|
std::vector<HlEdgeEntry*>* currNodeVector =
|
|
currNodeEntry->getEdgesVector();
|
|
|
|
for (std::vector<HlEdgeEntry*>::iterator
|
|
edgesVectorIter = currNodeVector->begin();
|
|
edgesVectorIter != currNodeVector->end();
|
|
++edgesVectorIter)
|
|
{
|
|
//get next edge
|
|
HlEdgeEntry* currEdgeEntry = *edgesVectorIter;
|
|
|
|
int currTargetNodeIndex = currEdgeEntry->getTargetIndex();
|
|
|
|
int currEdgeParentIndexForward =
|
|
currEdgeEntry->getParentIndexForward();
|
|
int currEdgeParentIndexReverse =
|
|
currEdgeEntry->getParentIndexReverse();
|
|
|
|
int currTargetNodeId = -1;
|
|
if(currTargetNodeIndex > -1)
|
|
{
|
|
HlNodeEntry* currTargetNodeEntry =
|
|
nodesEdgesVector[currTargetNodeIndex];
|
|
currTargetNodeId = currTargetNodeEntry->getNodeId();
|
|
}
|
|
|
|
int currEdgeParentIdForward = -1;
|
|
if(currEdgeParentIndexForward > -1)
|
|
{
|
|
HlNodeEntry* currParentNodeEntryForward =
|
|
nodesEdgesVector[currEdgeParentIndexForward];
|
|
currEdgeParentIdForward =
|
|
currParentNodeEntryForward->getNodeId();
|
|
}
|
|
|
|
int currEdgeParentIdReverse = -1;
|
|
if(currEdgeParentIndexReverse > -1)
|
|
{
|
|
HlNodeEntry* currParentNodeEntryReverse =
|
|
nodesEdgesVector[currEdgeParentIndexReverse];
|
|
currEdgeParentIdReverse =
|
|
currParentNodeEntryReverse->getNodeId();
|
|
}
|
|
|
|
int isForwardInt = 0;
|
|
int isReverseInt = 0;
|
|
if(currEdgeEntry->getIsForward())
|
|
{
|
|
isForwardInt = 1;
|
|
}
|
|
if(currEdgeEntry->getIsReverse())
|
|
{
|
|
isReverseInt = 1;
|
|
}
|
|
|
|
//create orelTuple
|
|
ListExpr relTypeSource;
|
|
nl->ReadFromString(HubLabelClass::hlGetHlGraphOrelTypeInfo(),
|
|
relTypeSource);
|
|
ListExpr tupleNumTypeSource =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relTypeSource));
|
|
Tuple* insertTuple = new Tuple(tupleNumTypeSource);
|
|
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_SOURCE_IN_HL_GRAPH,
|
|
new CcInt(true, currSourceNodeId));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_TARGET_IN_HL_GRAPH,
|
|
new CcInt(true, currTargetNodeId));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_SOURCE_INDEX_IN_HL_GRAPH,
|
|
new CcInt(true, currSourceNodeIndex));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_TARGET_INDEX_IN_HL_GRAPH,
|
|
new CcInt(true, currTargetNodeIndex));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_SOURCE_RANK_IN_HL_GRAPH,
|
|
new CcInt(true, currNodeRank));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_IS_FORWARD_IN_HL_GRAPH,
|
|
new CcInt(true, isForwardInt));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_IS_REVERSE_IN_HL_GRAPH,
|
|
new CcInt(true, isReverseInt));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_PARENT_ID_FORWARD_IN_HL_GRAPH,
|
|
new CcInt(true, currEdgeParentIdForward));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_PARENT_ID_REVERSE_IN_HL_GRAPH,
|
|
new CcInt(true, currEdgeParentIdReverse));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_PARENT_INDEX_FORWARD_IN_HL_GRAPH,
|
|
new CcInt(true, currEdgeParentIndexForward));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_PARENT_INDEX_REVERSE_IN_HL_GRAPH,
|
|
new CcInt(true, currEdgeParentIndexReverse));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_WEIGHT_FORWARD_IN_HL_GRAPH,
|
|
new CcReal(true, currEdgeEntry->getWeightForward()));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_WEIGHT_REVERSE_IN_HL_GRAPH,
|
|
new CcReal(true, currEdgeEntry->getWeightReverse()));
|
|
|
|
reTransformedGraphOrel->AppendTuple(insertTuple);
|
|
|
|
insertTuple->DeleteIfAllowed();
|
|
insertTuple = 0;
|
|
|
|
delete currEdgeEntry;
|
|
}
|
|
delete currNodeVector;
|
|
delete currNodeEntry;
|
|
}
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlTransformOrelToHlGraphVM" << endl);
|
|
#endif
|
|
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
Takes an OSM-Graph (Orel Edges) and creates an HlGraph and contracts it.
|
|
Retrieves an Orel-Representation of that contracted graph.
|
|
This in turn can be used for performing a CH Search of to create HL Labels.
|
|
|
|
|
|
*/
|
|
int hlDoContractionOfHlGraphVM (Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEINFO
|
|
LogInfo("start hlDoContractionOfHlGraphVM" << endl);
|
|
#endif
|
|
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
#ifdef USEPERF
|
|
double perfTime = k->getCurrentTimeInMs();
|
|
double perfTime2 = 0.0;
|
|
double perfTime3 = 0.0;
|
|
double perfTime4 = 0.0;
|
|
double perfTime5 = 0.0;
|
|
double perfTime6 = 0.0;
|
|
double perfTime7 = 0.0;
|
|
double perfTime8 = 0.0;
|
|
#endif
|
|
|
|
|
|
OrderedRelation* edgesOrelSource = (OrderedRelation*) args[0].addr;
|
|
OrderedRelation* nodesOrel = (OrderedRelation*) args[1].addr;
|
|
CcInt* hHopSizeCcInt = (CcInt*) args[2].addr;
|
|
CcInt* skipContractionRemainingCountCcInt = (CcInt*) args[3].addr;
|
|
CcInt* currCalcFunctionCcInt = (CcInt*) args[4].addr;
|
|
|
|
int skipContractionRemainingCount =
|
|
skipContractionRemainingCountCcInt->GetIntval();
|
|
if(skipContractionRemainingCount < 0)
|
|
{
|
|
skipContractionRemainingCount = 0;
|
|
}
|
|
|
|
int hHopSize = hHopSizeCcInt->GetIntval();
|
|
|
|
if(hHopSize < 0)
|
|
{
|
|
hHopSize = 0;
|
|
}
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(s); // use the result storage
|
|
OrderedRelation* reTransformedGraphOrel =
|
|
(OrderedRelation*) result.addr; // cast the result
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("result gelesen" << endl);
|
|
#endif
|
|
|
|
int nodesCount = nodesOrel->GetNoTuples();
|
|
k->setProgressInterval(nodesCount / 10); //ganzzahlige division
|
|
|
|
//initialize vector with number of nodes
|
|
// such that we can use []-operator of vector instead using push_back
|
|
std::vector<HlNodeEntry*> nodesEdgesVector(nodesCount);
|
|
|
|
HubLabelClass::PriorityQueueType priorityQueue;
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("los transform" << endl);
|
|
#endif
|
|
|
|
#ifdef USEPERF
|
|
perfTime2 = k->getCurrentTimeInMs();
|
|
#endif
|
|
|
|
k->hlTransformOrelToHlGraph(nodesOrel, edgesOrelSource, nodesEdgesVector);
|
|
|
|
#ifdef USEPERF
|
|
perfTime3 = k->getCurrentTimeInMs();
|
|
LogPerf("perf: duration of transformation: (ms) "
|
|
<< fixed << (perfTime3 - perfTime2) << endl);
|
|
#endif
|
|
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("init priority queue" << endl);
|
|
#endif
|
|
k->hlInitPriorityQueueOfHlGraph(nodesEdgesVector, priorityQueue,
|
|
currCalcFunctionCcInt->GetIntval());
|
|
|
|
#ifdef USEPERF
|
|
perfTime4 = k->getCurrentTimeInMs();
|
|
LogPerf("perf: duration of init priority queue: (ms) "
|
|
<< fixed << (perfTime4 - perfTime3) << endl);
|
|
#endif
|
|
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("los contraction" << endl);
|
|
#endif
|
|
k->hlDoContractionOfHlGraph(nodesEdgesVector, priorityQueue,
|
|
hHopSize, skipContractionRemainingCount,
|
|
currCalcFunctionCcInt->GetIntval());
|
|
|
|
#ifdef USEPERF
|
|
perfTime5 = k->getCurrentTimeInMs();
|
|
LogPerf("perf: duration of full contraction: (ms) "
|
|
<< fixed << (perfTime5 - perfTime4)<< endl);
|
|
#endif
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("create upward downward graph" << endl);
|
|
#endif
|
|
k->hlCreateUpwardAndDownwardHlGraph(nodesEdgesVector);
|
|
|
|
#ifdef USEPERF
|
|
perfTime6 = k->getCurrentTimeInMs();
|
|
LogPerf("perf: duration of up-/ downwardsgraph creation: (ms) "
|
|
<< fixed << (perfTime6 - perfTime5) << endl);
|
|
#endif
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("fertig" << endl);
|
|
#endif
|
|
|
|
|
|
//convert nodesEdgesVector back to OrderedRelation
|
|
for (uint currSourceNodeIndex = 0;
|
|
currSourceNodeIndex < nodesEdgesVector.size();
|
|
currSourceNodeIndex++)
|
|
{
|
|
HlNodeEntry* currSourceNodeEntry =
|
|
nodesEdgesVector[currSourceNodeIndex];
|
|
int currSourceNodeId = currSourceNodeEntry->getNodeId();
|
|
int currSourceNodeRank = currSourceNodeEntry->getRankValue();
|
|
std::vector<HlEdgeEntry*>* currSourceNodeEdgesVector =
|
|
currSourceNodeEntry->getEdgesVector();
|
|
|
|
|
|
//check whether the currSourceNodeEdgesVector is empty
|
|
//this is the case if we process the highest rank value
|
|
//we need to insert an empty edge leading to target == -1
|
|
// just for persistance purposes
|
|
//because else we would lose information about the highest rank
|
|
// vertext at all
|
|
|
|
if(currSourceNodeEdgesVector->empty())
|
|
{
|
|
|
|
HlEdgeEntry* highestRankVertexDummyEdge = new HlEdgeEntry();
|
|
highestRankVertexDummyEdge->setTargetIndex(-1);
|
|
highestRankVertexDummyEdge->setIsForward(false);
|
|
highestRankVertexDummyEdge->setIsReverse(false);
|
|
highestRankVertexDummyEdge->setParentIndexForward(-1);
|
|
highestRankVertexDummyEdge->setParentIndexReverse(-1);
|
|
highestRankVertexDummyEdge->setWeightForward(0.0);
|
|
highestRankVertexDummyEdge->setWeightReverse(0.0);
|
|
currSourceNodeEdgesVector->push_back(highestRankVertexDummyEdge);
|
|
}
|
|
|
|
for (std::vector<HlEdgeEntry*>::iterator
|
|
currSourceNodeEdgesVectorIter = currSourceNodeEdgesVector->begin();
|
|
currSourceNodeEdgesVectorIter != currSourceNodeEdgesVector->end();
|
|
++currSourceNodeEdgesVectorIter)
|
|
{
|
|
|
|
//get next edge
|
|
HlEdgeEntry* currEdgeEntry = *currSourceNodeEdgesVectorIter;
|
|
|
|
int currTargetNodeIndex = currEdgeEntry->getTargetIndex();
|
|
|
|
int currEdgeParentIndexForward =
|
|
currEdgeEntry->getParentIndexForward();
|
|
int currEdgeParentIndexReverse =
|
|
currEdgeEntry->getParentIndexReverse();
|
|
|
|
int currEdgeParentIdForward = -1;
|
|
if(currEdgeParentIndexForward > -1)
|
|
{
|
|
HlNodeEntry* currParentNodeEntryForward =
|
|
nodesEdgesVector[currEdgeParentIndexForward];
|
|
currEdgeParentIdForward =
|
|
currParentNodeEntryForward->getNodeId();
|
|
}
|
|
|
|
int currEdgeParentIdReverse = -1;
|
|
if(currEdgeParentIndexReverse > -1)
|
|
{
|
|
HlNodeEntry* currParentNodeEntryReverse =
|
|
nodesEdgesVector[currEdgeParentIndexReverse];
|
|
currEdgeParentIdReverse =
|
|
currParentNodeEntryReverse->getNodeId();
|
|
}
|
|
|
|
//in case of highest rank vertex the current targetIndex is -1
|
|
int currTargetNodeId = -1;
|
|
if(currTargetNodeIndex != -1)
|
|
{
|
|
HlNodeEntry* currTargetNodeEntry =
|
|
nodesEdgesVector[currTargetNodeIndex];
|
|
|
|
currTargetNodeId = currTargetNodeEntry->getNodeId();
|
|
}
|
|
|
|
int isForwardInt = 0;
|
|
int isReverseInt = 0;
|
|
|
|
if(currEdgeEntry->getIsForward())
|
|
{
|
|
isForwardInt = 1;
|
|
}
|
|
|
|
if(currEdgeEntry->getIsReverse())
|
|
{
|
|
isReverseInt = 1;
|
|
}
|
|
|
|
//create orelTuple
|
|
ListExpr relTypeSource;
|
|
nl->ReadFromString(HubLabelClass::hlGetHlGraphOrelTypeInfo(),
|
|
relTypeSource);
|
|
ListExpr tupleNumTypeSource =
|
|
SecondoSystem::GetCatalog()->NumericType(
|
|
nl->Second(relTypeSource));
|
|
Tuple* insertTuple = new Tuple(tupleNumTypeSource);
|
|
|
|
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_SOURCE_IN_HL_GRAPH,
|
|
new CcInt(true, currSourceNodeId));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_TARGET_IN_HL_GRAPH,
|
|
new CcInt(true, currTargetNodeId));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_SOURCE_INDEX_IN_HL_GRAPH,
|
|
new CcInt(true, currSourceNodeIndex));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_TARGET_INDEX_IN_HL_GRAPH,
|
|
new CcInt(true, currTargetNodeIndex));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_SOURCE_RANK_IN_HL_GRAPH,
|
|
new CcInt(true, currSourceNodeRank));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_IS_FORWARD_IN_HL_GRAPH,
|
|
new CcInt(true, isForwardInt));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_IS_REVERSE_IN_HL_GRAPH,
|
|
new CcInt(true, isReverseInt));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_PARENT_ID_FORWARD_IN_HL_GRAPH,
|
|
new CcInt(true, currEdgeParentIdForward));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_PARENT_ID_REVERSE_IN_HL_GRAPH,
|
|
new CcInt(true, currEdgeParentIdReverse));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_PARENT_INDEX_FORWARD_IN_HL_GRAPH,
|
|
new CcInt(true, currEdgeParentIndexForward));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_PARENT_INDEX_REVERSE_IN_HL_GRAPH,
|
|
new CcInt(true, currEdgeParentIndexReverse));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_WEIGHT_FORWARD_IN_HL_GRAPH,
|
|
new CcReal(true, currEdgeEntry->getWeightForward()));
|
|
insertTuple->PutAttribute(
|
|
HubLabelClass::HL_INDEX_OF_WEIGHT_REVERSE_IN_HL_GRAPH,
|
|
new CcReal(true, currEdgeEntry->getWeightReverse()));
|
|
|
|
|
|
reTransformedGraphOrel->AppendTuple(insertTuple);
|
|
|
|
insertTuple->DeleteIfAllowed();
|
|
insertTuple = 0;
|
|
|
|
delete currEdgeEntry;
|
|
|
|
}
|
|
delete currSourceNodeEdgesVector;
|
|
}
|
|
|
|
#ifdef USEPERF
|
|
perfTime7 = k->getCurrentTimeInMs();
|
|
LogPerf("perf: duration of retransforming into orel: (ms) "
|
|
<< fixed << (perfTime7 - perfTime6) << endl);
|
|
#endif
|
|
|
|
//again iterate through nodesEdgesVector to delete all nodeEntries
|
|
// we could not do this before
|
|
for(std::vector<HlNodeEntry*>::iterator nodesEdgesVectorIter2
|
|
= nodesEdgesVector.begin(); nodesEdgesVectorIter2
|
|
!= nodesEdgesVector.end(); nodesEdgesVectorIter2++)
|
|
{
|
|
|
|
HlNodeEntry* currSourceNodeEntry2 = *nodesEdgesVectorIter2;
|
|
delete currSourceNodeEntry2;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
#ifdef USEPERF
|
|
perfTime8 = k->getCurrentTimeInMs();
|
|
LogPerf("perf: duration of clearing memory: (ms) "
|
|
<< fixed << (perfTime8 - perfTime7) << endl);
|
|
LogPerf("perf: duration of full contraction operator: (ms) "
|
|
<< fixed << (perfTime8 - perfTime) << endl);
|
|
#endif
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("finish hlDoContractionOfHlGraphVM" << endl);
|
|
#endif
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
Takes an Orel-Representation of a HlGraph.
|
|
Performs a CH search.
|
|
Retrieves the shortest path of the search represented by an Orel
|
|
of edges from the given OSM-graph.
|
|
|
|
|
|
*/
|
|
int hlDoChSearchInHlGraphVM (Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEINFO
|
|
LogInfo("start hlDoChSearchInHlGraphVM" << endl);
|
|
#endif
|
|
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
#ifdef USEPERF
|
|
double perfTime = k->getCurrentTimeInMs();
|
|
double perfTime2 = 0.0;
|
|
double perfTime3 = 0.0;
|
|
double perfTime4 = 0.0;
|
|
double perfTime5 = 0.0;
|
|
double perfTime6 = 0.0;
|
|
#endif
|
|
|
|
|
|
OrderedRelation* nodesOrel = (OrderedRelation*) args[0].addr;
|
|
OrderedRelation* edgesSourceOrel = (OrderedRelation*) args[1].addr;
|
|
OrderedRelation* contractedHlGraphOrel = (OrderedRelation*) args[2].addr;
|
|
CcInt* SourceCcInt = (CcInt*) args[3].addr;
|
|
CcInt* targetCcInt = (CcInt*) args[4].addr;
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(s); // use the result storage
|
|
Relation* shortestPathRel = (Relation*) result.addr; // cast the result
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("result gelesen" << endl);
|
|
#endif
|
|
|
|
|
|
//prepare data
|
|
bool isChElseHl = true;
|
|
int source = SourceCcInt->GetIntval();
|
|
int target = targetCcInt->GetIntval();
|
|
std::vector<HlNodeEntry*> nodesEdgesVector(nodesOrel->GetNoTuples());
|
|
|
|
#ifdef USEPERF
|
|
perfTime2 = k->getCurrentTimeInMs();
|
|
#endif
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("convert hlGraphOrel to hlGraph" << endl);
|
|
#endif
|
|
k->hlTransformHlGraphOrelToHlGraph(contractedHlGraphOrel, nodesEdgesVector);
|
|
|
|
#ifdef USEPERF
|
|
perfTime3 = k->getCurrentTimeInMs();
|
|
LogPerf("perf: duration of transformation: (ms) "
|
|
<< fixed << (perfTime3 - perfTime2) << endl);
|
|
#endif
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("do search" << endl);
|
|
#endif
|
|
std::tuple<int, double, std::map<int, ChNode*>> searchResultTuple =
|
|
k->hlDoCHSearch(nodesEdgesVector, source, target, isChElseHl);
|
|
|
|
#ifdef USEPERF
|
|
perfTime4 = k->getCurrentTimeInMs();
|
|
LogPerf("perf: duration CHSearch: (ms) "
|
|
<< fixed << (perfTime4 - perfTime3) << endl);
|
|
#endif
|
|
|
|
int shortestPathHubIndex = std::get<0>(searchResultTuple);
|
|
std::map<int, ChNode*> searchTree = std::get<2>(searchResultTuple);
|
|
|
|
#ifdef USEINFO
|
|
double shortestPathLength = std::get<1>(searchResultTuple);
|
|
#endif
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("resolve shortestpath" << endl);
|
|
#endif
|
|
|
|
k->hlResolveShortestPathFromSearchTree(shortestPathHubIndex,
|
|
nodesEdgesVector, searchTree, edgesSourceOrel, shortestPathRel);
|
|
|
|
#ifdef USEPERF
|
|
perfTime5 = k->getCurrentTimeInMs();
|
|
LogPerf("perf: duration of resolving shortest path: (ms) "
|
|
<< fixed << (perfTime5 - perfTime4) << endl);
|
|
#endif
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("fertig" << endl);
|
|
#endif
|
|
|
|
if(shortestPathHubIndex != -1)
|
|
{
|
|
#ifdef USEINFO
|
|
HlNodeEntry* hubNodeEntry = nodesEdgesVector[shortestPathHubIndex];
|
|
int hubNodeId = hubNodeEntry->getNodeId();
|
|
|
|
LogInfo("shortest path found start: " << source << " target: " << target
|
|
<< " hubNodeId: " << hubNodeId << " length: "
|
|
<< shortestPathLength << endl);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#ifdef USEINFO
|
|
LogInfo("no shortest path found start: "
|
|
<< source << " target: " << target
|
|
<< " hubNodeId: " << shortestPathHubIndex
|
|
<< " length: " << shortestPathLength << endl);
|
|
#endif
|
|
}
|
|
|
|
//free resources
|
|
k->hlFreeSearchTree(searchTree);
|
|
k->hlFreeHlGraph(nodesEdgesVector);
|
|
delete k;
|
|
|
|
|
|
#ifdef USEPERF
|
|
perfTime6 = k->getCurrentTimeInMs();
|
|
LogPerf("perf: duration of clearing memory: (ms) "
|
|
<< fixed << (perfTime6 - perfTime5) << endl);
|
|
LogPerf("perf: duration of complete CH serch operator: (ms) "
|
|
<< fixed << (perfTime6 - perfTime) << endl);
|
|
#endif
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("finish hlDoChSearchInHlGraphVM" << endl);
|
|
#endif
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
Takes an Orel-Representation of a HlGraph.
|
|
Performs multiple CH searches to create HubLabels.
|
|
|
|
|
|
*/
|
|
int hlCreateLabelsFromHlGraphVM (Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEINFO
|
|
LogInfo("start hlCreateLabelsFromHlGraphVM" << endl);
|
|
#endif
|
|
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
#ifdef USEPERF
|
|
double perfTime = k->getCurrentTimeInMs();
|
|
double perfTime2 = 0.0;
|
|
double perfTime3 = 0.0;
|
|
double perfTime4 = 0.0;
|
|
double perfTime5 = 0.0;
|
|
#endif
|
|
|
|
|
|
OrderedRelation* nodesOrel = (OrderedRelation*) args[0].addr;
|
|
OrderedRelation* contractedHlGraphOrel = (OrderedRelation*) args[1].addr;
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(s); // use the result storage
|
|
NestedRelation* allLabelsNrel = (NestedRelation*) result.addr;
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("result gelesen" << endl);
|
|
#endif
|
|
|
|
int nodesCount = nodesOrel->GetNoTuples();
|
|
k->setProgressInterval(nodesCount / 10); //ganzzahlige division
|
|
std::vector<HlNodeEntry*> nodesEdgesVector(nodesCount);
|
|
|
|
#ifdef USEPERF
|
|
perfTime2 = k->getCurrentTimeInMs();
|
|
#endif
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("convert hlGraphOrel to hlGraph" << endl);
|
|
#endif
|
|
k->hlTransformHlGraphOrelToHlGraph(contractedHlGraphOrel, nodesEdgesVector);
|
|
|
|
#ifdef USEPERF
|
|
perfTime3 = k->getCurrentTimeInMs();
|
|
LogPerf("perf: duration of transformation: (ms) "
|
|
<< fixed << (perfTime3 - perfTime2)<< endl);
|
|
#endif
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("Create Labels" << endl);
|
|
#endif
|
|
//also does delete hlGraph objects
|
|
k->hlCreateLabelsFromHlGraph(allLabelsNrel, nodesOrel, nodesEdgesVector);
|
|
|
|
|
|
#ifdef USEPERF
|
|
perfTime4 = k->getCurrentTimeInMs();
|
|
LogPerf("perf: duration of creating all hublabels: (ms) "
|
|
<< fixed << (perfTime4 - perfTime3)<< endl);
|
|
#endif
|
|
|
|
//free resources
|
|
k->hlFreeHlGraph(nodesEdgesVector);
|
|
delete k;
|
|
|
|
#ifdef USEPERF
|
|
perfTime5 = k->getCurrentTimeInMs();
|
|
LogPerf("perf: duration of complete operator for creating hublabels: (ms) "
|
|
<< fixed << (perfTime5 - perfTime)<< endl);
|
|
#endif
|
|
|
|
#ifdef USEINFO
|
|
LogInfo("finish hlCreateLabelsFromHlGraphVM" << endl);
|
|
#endif
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
Takes an Orel-Representation of an OSM-Graph.
|
|
Expects the Osm-Orel to fulfil the schema of
|
|
@see hlGetEdgesTupleTypeInfo()
|
|
Iterates over every edge and retrieves its Curves' length.
|
|
Gets the Edges RoadType and multiplies the length with a const value
|
|
dependent of the RoadType representing the average speed driven
|
|
when traversing this edge.
|
|
|
|
|
|
*/
|
|
int hlCalcWeightsOrelVM (Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start hlCalcWeightsOrelVM" << endl);
|
|
#endif
|
|
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
OrderedRelation* edgesSourceOrel = (OrderedRelation*) args[0].addr;
|
|
CcInt* calculationMode = (CcInt*) args[1].addr;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(s); // use the result storage
|
|
CcInt* resultInt = (CcInt*) result.addr; // cast the result
|
|
resultInt->Set(true, 1);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("los" << endl);
|
|
#endif
|
|
k->hlCalcWeightsOrel(edgesSourceOrel, calculationMode->GetIntval());
|
|
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish" << endl);
|
|
#endif
|
|
|
|
|
|
//free resources
|
|
delete k;
|
|
|
|
//Änderungen an als Parameter übergebenen Orels persistieren
|
|
qp->SetModified(qp->GetSon(s,0));
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish hlCalcWeightsOrelVM" << endl);
|
|
#endif
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
5.2.3 Value Mappings of (3) In-Memory Approach using MainMemory2Algebra
|
|
|
|
not yet implemented right
|
|
|
|
*/
|
|
template<class G1, class G2>
|
|
int hlContractMmGraphVMT(Word* args, Word& result,
|
|
int message, Word& local, Supplier s)
|
|
{
|
|
#ifdef USEDEBUG
|
|
LogDebug("start contractNewVM" << endl);
|
|
#endif
|
|
|
|
HubLabelClass* k = new HubLabelClass(1, 2, 3);
|
|
|
|
G1* oNUp = (G1*) args[0].addr;
|
|
G2* oNDown = (G2*) args[1].addr;
|
|
Word* calcFunction = (Word*) args[2].addr;
|
|
#ifdef USEDEBUG
|
|
LogDebug("Parameter gelesen" << endl);
|
|
#endif
|
|
|
|
result = qp->ResultStorage(s); // use the result storage
|
|
CcInt* resultInt = (CcInt*) result.addr; // cast the result
|
|
resultInt->Set(true, 1);
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("result gelesen" << endl);
|
|
#endif
|
|
|
|
mm2algebra::MemoryGraphObject* memgraphUp =
|
|
mm2algebra::getMemGraph(oNUp);
|
|
mm2algebra::MemoryGraphObject* memgraphDown =
|
|
mm2algebra::getMemGraph(oNDown);
|
|
|
|
if(!memgraphUp || !memgraphDown) {
|
|
return 0;
|
|
}
|
|
|
|
graph::Graph* graphUp = memgraphUp->getgraph();
|
|
graph::Graph* graphDown = memgraphDown->getgraph();
|
|
|
|
k->hlContractMmGraph(graphUp, graphDown, calcFunction);
|
|
|
|
|
|
delete k;
|
|
|
|
#ifdef USEDEBUG
|
|
LogDebug("finish contractNewVM" << endl);
|
|
#endif
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
5.3 Specification
|
|
|
|
The specification provides an operator description for the user.
|
|
The first argument of the ~OperatorSpec~ constructor is a description
|
|
of the type mapping, the second argument describes the syntax of
|
|
the operator, than comes the operator's meaning and the last argument
|
|
used here is an example query. If required, an additional
|
|
argument can provide some remark to this operator.
|
|
|
|
All specifications are related to the equal named function of the class
|
|
HubLabelClass.
|
|
The specifications just got an additional suffix 'Spec'
|
|
|
|
5.3.1 Specification of (1) Persistent Approach
|
|
|
|
*/
|
|
|
|
|
|
OperatorSpec hlCalcRankSpec(
|
|
"orel x orel x ccint -> real",
|
|
"hlCalcRank(_, _, _)",
|
|
"For testing purposes. "
|
|
"Computes and returns the rank of the given nodeId.",
|
|
"query hlCalcRank(EdgesOrelSource feed head[10] oconsume,"
|
|
" EdgesOreltarget feed head[10] oconsume, 12345678)"
|
|
);
|
|
|
|
|
|
OperatorSpec hlOneHopReverseSearchSpec(
|
|
"orel x orel x ccint -> orel",
|
|
"hlOneHopReverseSearch(_, _, _)",
|
|
"For testing purposes. "
|
|
"Processes a one hop reverse Search and returns an orel containing"
|
|
" the results.",
|
|
"query hlOneHopReverseSearch(EdgesTestOrelSource, EdgesTestOrelTarget,"
|
|
" 7264168)"
|
|
);
|
|
|
|
|
|
OperatorSpec hlHHopForwardSearchSpec(
|
|
"orel x ore x orel x ccint x ccint -> real",
|
|
"hlHHopForwardSearch(_, _, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlHHopForwardSearch(orelEdgesSource, orelEdgesTarget,"
|
|
" multimapReverseSearchXT, contractNodeV, hHop)",
|
|
"query hlHHopForwardSearch(orelEdgesSource, orelEdgesTarget,"
|
|
" multimapReverseSearchXT, 1505, -1) feed consume"
|
|
);
|
|
|
|
|
|
OperatorSpec hlForwardSearchGetDistSpec(
|
|
"orel x ccint x ccint -> real",
|
|
"hlForwardSearchGetDist(_, _, _)",
|
|
"For testing purposes. "
|
|
"hlForwardSearchGetDist(oneHopReverseSearchOrelXT, contractNodeV,"
|
|
" currentTargetNodeT)",
|
|
"query hlForwardSearchGetDist(OneHopReverseSearchToBeDeleted, 7264168,"
|
|
" 7264033)"
|
|
);
|
|
|
|
|
|
OperatorSpec hlRemoveTFromCurrentWitnessListSpec(
|
|
"orel x ccint -> orel",
|
|
"hlRemoveTFromCurrentWitnessList(_, _)",
|
|
"For testing purposes. "
|
|
"hlRemoveTFromCurrentWitnessList(oneHopReverseSearchOrelXT,"
|
|
" currentTargetNodeT)",
|
|
"query hlRemoveTFromCurrentWitnessList(OneHopReverseSearchToBeDeleted,"
|
|
" 7264033)"
|
|
);
|
|
|
|
|
|
OperatorSpec
|
|
hlForwardSearchCheckForWitnessPathSpec(
|
|
"orel x ccint x ccint x ccreal x ccreal -> orel",
|
|
"hlForwardSearchCheckForWitnessPath(_, _, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlForwardSearchCheckForWitnessPath(oneHopReverseSearchOrelXT,"
|
|
" contractNodeV, currentNodeX, distSX, distSV)",
|
|
"query hlForwardSearchCheckForWitnessPath("
|
|
"OneHopReverseSearchToBeDeleted2, 1505, 1495, 6.16, 42,453) feed"
|
|
" consume"
|
|
);
|
|
|
|
|
|
OperatorSpec
|
|
hlInsertOrUpdateTupleInNotYetVisitedListSpec(
|
|
"rel x ccint x ccint x ccint -> orel",
|
|
"hlInsertOrUpdateTupleInNotYetVisitedList(_, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlInsertOrUpdateTupleInNotYetVisitedList(EdgesSourceTmpRel,"
|
|
" currentNodeV, currentNodeS, isForward)",
|
|
"query hlInsertOrUpdateTupleInNotYetVisitedList(EdgesTestRelSourceTmp,"
|
|
" 1492, 1424, 1) feed consume"
|
|
);
|
|
|
|
|
|
OperatorSpec
|
|
hlForwardSearchIterativeStepsScanNewVerticesSpec(
|
|
"orel x orel x orel x orel x rel x ccint x ccreal -> ccin",
|
|
"hlForwardSearchIterativeStepsScanNewVertices(_, _, _, _, _, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlForwardSearchIterativeStepsScanNewVertices(EdgesTestOrelSource,"
|
|
" hlNotYetVisitedNodesTest, stillVisitedNodesOrel,"
|
|
" OneHopReverseSearchToBeDeleted2,"
|
|
" currMinNotYetVisitedNodesSingleTupleOrelFwdW, 1424, 30.00)",
|
|
"query hlForwardSearchIterativeStepsScanNewVertices("
|
|
"EdgesTestOrelSource, hlNotYetVisitedNodesTest, stillVisitedNodesOrel,"
|
|
" OneHopReverseSearchToBeDeleted2,"
|
|
" currMinNotYetVisitedNodesSingleTupleOrelFwdW, 1424, 30.00)"
|
|
);
|
|
|
|
|
|
OperatorSpec
|
|
hlForwardSearchProcessIncomingEdgeIterativeStepsSpec(
|
|
"orel x orel x orel x orel x ccint x ccint x ccreal -> cint",
|
|
"hlForwardSearchProcessIncomingEdgeIterativeSteps(_, _, _, _, _, _, _,"
|
|
" _)",
|
|
"For testing purposes. "
|
|
"hlForwardSearchProcessIncomingEdgeIterativeSteps(EdgesTestOrelSource,"
|
|
" hlNotYetVisitedNodesTest, stillVisitedNodesOrel, hHop, nodeV,"
|
|
" distSV)",
|
|
"query hlForwardSearchProcessIncomingEdgeIterativeSteps("
|
|
"EdgesTestOrelSource, hlNotYetVisitedNodesTest, stillVisitedNodesOrel,"
|
|
" OneHopReverseSearchToBeDeleted2, 999, 1424, 30.00)"
|
|
);
|
|
|
|
|
|
OperatorSpec
|
|
hlForwardSearchProcessIncomingEdgeInitialStepsSpec(
|
|
"orel x orel x orel x ccint x ccint x ccreal -> cint",
|
|
"hlForwardSearchProcessIncomingEdgeInitialSteps(_, _, _, _, _, _,)",
|
|
"For testing purposes. "
|
|
"hlForwardSearchProcessIncomingEdgeInitialSteps(EdgesTestOrelSource,"
|
|
" hlNotYetVisitedNodesTes, hlOneHopReverseSearchXTOrel, nodeS, nodeV,"
|
|
" distSV)",
|
|
"query hlForwardSearchProcessIncomingEdgeInitialSteps("
|
|
"hlEdgesOrelSource, hlNotYetVisitedNodesCopyOrelDist,"
|
|
" hlOneHopReverseSearchXTOrelX3, 1492, 1505, 6.16);"
|
|
);
|
|
|
|
|
|
OperatorSpec
|
|
hlForwardSearchCreateAndAppendShortcutsSpec(
|
|
"orel x ccint x ccint x ccreal -> orel",
|
|
"hlForwardSearchCreateAndAppendShortcuts(_, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlForwardSearchCreateAndAppendShortcuts(copyMultimapReverseSearchXT,"
|
|
" currentSourceNodeFwdS, currentVertexIdFwdV, distSV) feed consume",
|
|
"query hlForwardSearchCreateAndAppendShortcuts("
|
|
"copyMultimapReverseSearchXT, 1492, 1505, 1000.0) feed consume"
|
|
);
|
|
|
|
|
|
OperatorSpec
|
|
hlForwardSearchProcessIncomingEdgeSpec(
|
|
"orel x orel x orel x orel x ccint x ccint x ccint x ccreal -> orel",
|
|
"hlForwardSearchProcessIncomingEdge(_, _, _, _, _, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlForwardSearchProcessIncomingEdge(hlEdgesOrelSource,"
|
|
" stillVisitedNodesOrel, copyMultimapReverseSearchXT,"
|
|
" hlShortcutstoBeAdded, currentSourceNodeFwdS, currentVertexIdFwdV,"
|
|
" hDepth, distSV) feed consume",
|
|
"query hlForwardSearchProcessIncomingEdge(hlEdgesOrelSource,"
|
|
" stillVisitedNodesOrel, copyMultimapReverseSearchXT,"
|
|
" hlShortcutstoBeAdded, 1492, 1505, 2, 1000.00) feed consume"
|
|
);
|
|
|
|
|
|
OperatorSpec
|
|
hlRemoveContractedEdgesFromEdgesRelationsSpec(
|
|
"orel x orel x ccint -> ccint",
|
|
"hlRemoveContractedEdgesFromEdgesRelations(_, _, _)",
|
|
"For testing purposes. "
|
|
"hlRemoveContractedEdgesFromEdgesRelations(hlEdgesOrelSourceCopy,"
|
|
" hlEdgesOrelTargetCopy, hlCurrentContractV)",
|
|
"query hlRemoveContractedEdgesFromEdgesRelations(hlEdgesOrelSource,"
|
|
" hlEdgesOrelTarget, 1505)"
|
|
);
|
|
|
|
|
|
OperatorSpec
|
|
hlRemoveParallelEdgesFromEdgesRelationsSpec(
|
|
"orel x orel x orel -> ccint",
|
|
"hlRemoveParallelEdgesFromEdgesRelations(_, _, _)",
|
|
"For testing purposes. "
|
|
"hlRemoveParallelEdgesFromEdgesRelations(hlEdgesOrelSourceCopy,"
|
|
" hlEdgesOrelTargetCopy, hlShortcutsToBeCreatedOrelToBeDeleted)",
|
|
"query hlRemoveParallelEdgesFromEdgesRelations(hlEdgesOrelSource,"
|
|
" hlEdgesOrelTarget, hlShortcutsToBeCreatedOrelToBeDeleted)"
|
|
);
|
|
|
|
|
|
OperatorSpec hlDoContractionSpec(
|
|
"orel x orel x ccint x ccint -> orel",
|
|
"hlDoContraction(_, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlDoContraction(edgesWithViaOrelSource, edgesWithViaOrelTarget,"
|
|
" currentVToBeContracted, hHop) feed consume",
|
|
"query hlDoContraction(edgesWithViaOrelSource, edgesWithViaOrelTarget,"
|
|
" 1505, 2) feed consume"
|
|
);
|
|
|
|
|
|
OperatorSpec
|
|
hlIterateOverAllNodesByRankAscAndDoContractionSpec(
|
|
"orel x orel x orel x ccint -> ccint",
|
|
"hlIterateOverAllNodesByRankAscAndDoContraction(_, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlIterateOverAllNodesByRankAscAndDoContraction(nodesWithRankOrelRank,"
|
|
" edgesWithViaOrelSource, edgesWithViaOrelTarget, hHop)",
|
|
"query hlIterateOverAllNodesByRankAscAndDoContraction("
|
|
"nodesWithRankOrelRank, edgesWithViaOrelSource,"
|
|
" edgesWithViaOrelTarget, 2)"
|
|
);
|
|
|
|
|
|
OperatorSpec
|
|
hlCreateLabelCheckForWitnessScanNewVerticesSpec(
|
|
"orel x orel x ccint x ccint x ccreal x ccint (ccbool) -> orel",
|
|
"hlCreateLabelCheckForWitnessScanNewVertices(_, _, _, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlCreateLabelCheckForWitnessScanNewVertices(hlUpwardEdgesOrelSource,"
|
|
" hlDownwardEdgesOrelTarget, nextNodeToScan, nextNodeHHop,"
|
|
" NextNodeDistToSource, isForward) feed consume",
|
|
"query hlCreateLabelCheckForWitnessScanNewVertices("
|
|
"hlUpwardEdgesOrelSource, hlDownwardEdgesOrelTarget, 1496, 1, 1000.0,"
|
|
" 1) feed consume"
|
|
);
|
|
|
|
|
|
OperatorSpec hlCreateLabelCheckForWitnessSpec(
|
|
"orel x orel x rel x ccint x ccint x ccreal x ccint (ccbool) -> ccint"
|
|
" (ccbool)",
|
|
"hlCreateLabelCheckForWitness(_, _, _, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlCreateLabelCheckForWitness(hlUpwardEdgesOrelSource,"
|
|
" hlDownwardEdgesOrelTarget, hlFwdOrRvsLabel, currentNode, hlhHop,"
|
|
" currentNodeDistToSource, isForward)",
|
|
"query hlCreateLabelCheckForWitness(hlUpwardEdgesOrelSource,"
|
|
" hlDownwardEdgesOrelTarget, hlFwdOrRvsLabel, 273, 10, 0.0, 1)"
|
|
);
|
|
|
|
|
|
OperatorSpec hlCreateLabelScanNewVerticesSpec(
|
|
"orel x orel x rel x ccint x ccreal x ccint (ccbool) -> orel",
|
|
"hlCreateLabelScanNewVertices(_, _, _, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlCreateLabelScanNewVertices(hlUpwardEdgesOrelSource,"
|
|
" hlDownwardEdgesOrelTarget, hlFwdOrRvsLabel, currentNode,"
|
|
" currentNodeDistToSource, isForward) feed consume",
|
|
"query hlCreateLabelScanNewVertices(hlUpwardEdgesOrelSource,"
|
|
" hlDownwardEdgesOrelTarget, hlFwdOrRvsLabel, 273, 0.0, 1) feed"
|
|
" consume"
|
|
);
|
|
|
|
|
|
OperatorSpec hlGetRankByIdSpec(
|
|
"btree x orel x ccint -> orel",
|
|
"hlGetRankById(_, _, _)",
|
|
"For testing purposes. "
|
|
"hlGetRankById(hlNodesWithRankOrelRank_NodeIdNew,"
|
|
" hlNodesWithRankOrelRank, givenNodeId) feed consume",
|
|
"query hlGetRankById(hlNodesWithRankOrelRank_NodeIdNew,"
|
|
" hlNodesWithRankOrelRank, 700) feed consume"
|
|
);
|
|
|
|
|
|
OperatorSpec
|
|
hlCreateLabelByDijkstraWithStallingSpec(
|
|
"btree x orel x orel x orel x Ccint x ccint x ccint (ccbool) -> orel",
|
|
"hlCreateLabelByDijkstraWithStalling(_, _, _, _, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlCreateLabelByDijkstraWithStalling(hlNodesWithRankOrelRank_NodeIdNew,"
|
|
" hlNodesWithRankOrelRank, hlEdgesWithViaOrelSource,"
|
|
" hlEdgesWithViaOrelTarget, sourceNodeId, hHop, calcFunction) feed"
|
|
" consume",
|
|
"query hlCreateLabelByDijkstraWithStalling("
|
|
"hlNodesWithRankOrelRank_NodeIdNew, hlNodesWithRankOrelRank,"
|
|
" hlEdgesWithViaOrelSource, hlEdgesWithViaOrelTarget, 700, 10, 1)"
|
|
" feed consume"
|
|
);
|
|
|
|
|
|
OperatorSpec hlFillForwardOrReverseLabelSpec(
|
|
"Rel -> Nrel",
|
|
"hlFillForwardOrReverseLabel(_)",
|
|
"For testing purposes. "
|
|
"hlFillForwardOrReverseLabel(fwdOrRvsLabelRel) feed consume",
|
|
"query hlFillForwardOrReverseLabel(fwdOrRvsLabelRel) feed consume"
|
|
);
|
|
|
|
|
|
OperatorSpec hlGetPathViaPointsSpec(
|
|
"Nrel x Btree x Orel x Int x Int x Bool -> Rel",
|
|
"hlGetPathViaPoints(_, _, _, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlGetPathViaPoints(allLabelsNRel, allLabelsBTree,"
|
|
" hlEdgesOrelSourceParentVia, rootNodeId, hubId, isForward) feed"
|
|
" consume",
|
|
"query hlGetPathViaPoints(allLabelsNRel, allLabelsBTree,"
|
|
" hlEdgesOrelSourceParentVia, 62, 630, 1) feed consume"
|
|
);
|
|
|
|
|
|
OperatorSpec hlQuerySpec(
|
|
"Nrel x Btree x Orel x Int x Int x Bool -> Rel",
|
|
"hlQuery(_, _, _, _, _, _)",
|
|
"Performs a HubLabeling query using the given Nrel containing all Hub Label"
|
|
", the BTree over this Nrel, an Orel containing all Edges ordered by"
|
|
" its sourcenode, the sourceNodeId and targetNodeId of this search and"
|
|
" and a boolean to define the mode (only use 1).",
|
|
"query hlQuery(allLabelsNRel, allLabelsBTree,"
|
|
" hlEdgesOrelSourceParentVia, 62, 630, 1)"
|
|
);
|
|
|
|
|
|
OperatorSpec hlPruneLabelByBootstrappingSpec(
|
|
"Orel x Orel x Orel x Int x Int -> Int",
|
|
"hlPruneLabelByBootstrapping(_, _, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlPruneLabelByBootstrapping(nodesWithRankOrelRank,"
|
|
" edgesWithViaOrelSource, edgesWithViaOrelTarget, hHop, calcFunction)",
|
|
"query hlPruneLabelByBootstrapping(nodesWithRankOrelRank,"
|
|
" edgesWithViaOrelSource, edgesWithViaOrelTarget, 2, 1)"
|
|
);
|
|
|
|
|
|
OperatorSpec hlReorderLabelsSpec(
|
|
"Orel x Orel x Orel x Int x Int -> Int",
|
|
"hlReorderLabels(_, _, _, _, _)",
|
|
"For testing purposes. "
|
|
"hlReorderLabels(nodesWithRankOrelRank, edgesWithViaOrelSource,"
|
|
" edgesWithViaOrelTarget, hHop, calcFunction)",
|
|
"query hlReorderLabels(nodesWithRankOrelRank, edgesWithViaOrelSource,"
|
|
" edgesWithViaOrelTarget, 2, 1)"
|
|
);
|
|
|
|
|
|
OperatorSpec hlCreateLabelsSpec(
|
|
"Btree x Orel x Orel x Orel x Int -> Nrel",
|
|
"hlCreateLabels(_, _, _, _)",
|
|
"For testing purposes. "
|
|
"query hlCreateLabels(hlNodesWithRankOrelRank_NodeIdNew,"
|
|
" nodesWithRankOrelRank, hlUpwardEdgesOrelSourceParentVia,"
|
|
" hlDownwardEdgesOrelTargetParentVia, hHop) feed consume)",
|
|
"query hlCreateLabels(hlNodesWithRankOrelRank_NodeIdNew,"
|
|
" nodesWithRankOrelRank, hlUpwardEdgesOrelSourceParentVia,"
|
|
" hlDownwardEdgesOrelTargetParentVia, 10) feed consume"
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
5.3.2 Specification of (2) In-Memory Approach
|
|
|
|
*/
|
|
|
|
OperatorSpec hlTransformOrelToHlGraphSpec(
|
|
"Orel x Orel -> Orel",
|
|
"hlTransformOrelToHlGraph(_,_)",
|
|
"For testing purposes. "
|
|
"Reads the given edges-orel and nodes-orel into main memory"
|
|
" and does nothing else",
|
|
"query hlTransformOrelToHlGraph(hlEdgesOrelSource, hlNodesSourceOnlyOrel)"
|
|
"feed consume"
|
|
);
|
|
|
|
|
|
OperatorSpec hlDoContractionOfHlGraphSpec(
|
|
"Orel x Orel x Int x Int x Int -> Orel",
|
|
"hlDoContractionOfHlGraph(_, _, _, _, _)",
|
|
"Performs the contraction of the given edges-orel and nodes-orel."
|
|
" Takes also a desired hop-size for h-hop searches, a skip-parameter"
|
|
" to define to stop recalculating node-priorities after that many nodes"
|
|
" are left to be contracted and at least it takes an integer to define"
|
|
" which function shall be used to calculate node priorities"
|
|
" (0 = EdgeDifference; 1 = Random; 2 = InputOrder)."
|
|
" Returns the contracted graph (hlGraph) as OrderedRelation.",
|
|
"query hlDoContractionOfHlGraph(hlEdgesOrelSource, hlNodesSourceOnlyOrel,"
|
|
" 2, 50000, 0) feed consume"
|
|
);
|
|
|
|
|
|
OperatorSpec hlDoChSearchInHlGraphSpec(
|
|
"Orel x Orel x Orel x Int x Int -> Rel",
|
|
"hlDoChSearchInHlGraph(_, _, _, _, _)",
|
|
"Performs a CH search using the given nodes-orel, edges-orel,"
|
|
" the hlGraph of a previous contraction and the source- and targetNodeId"
|
|
" Returns a relation containing all edges on the shortest path in"
|
|
" their order of occurence on that path. Is empty if no path was found.",
|
|
"query hlDoChSearchInHlGraph(hlNodesSourceOnlyOrel, hlEdgesOrelSource,"
|
|
" hlGraphOrel, 1030, 2456) feed consume"
|
|
);
|
|
|
|
|
|
OperatorSpec hlCalcWeightsOrelSpec(
|
|
"Orel x Int -> Int",
|
|
"hlCalcWeightsOrel(_, _)",
|
|
"Takes the given edges-orel and calculates the edge-weight for every"
|
|
" edge using the calculation mode defined with the second parameter"
|
|
" (which currently is not supported, so ever use 1) and"
|
|
" stores the weight directly with the edge of the given orel.",
|
|
"query hlCalcWeightsOrel(hlEdgesOrelSource, 1) consume"
|
|
);
|
|
|
|
|
|
OperatorSpec hlCreateLabelsFromHlGraphSpec(
|
|
"Orel x Orel -> Nrel",
|
|
"hlCreateLabelsFromHlGraph(_, _)",
|
|
"Takes the node-orel and the previous contracted hlGraph and"
|
|
" creates Hub Label for every node of the node-orel."
|
|
" Returns a Nrel containing all Hub Label.",
|
|
"query hlCreateLabelsFromHlGraph(hlNodesSourceOnlyOrel, hlGraphOrel)"
|
|
" feed consume"
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
5.3.3 Specification of (3) In-Memory Approach using MainMemory2Algebra
|
|
|
|
*/
|
|
|
|
|
|
OperatorSpec hlContractMmGraphSpec(
|
|
"memgraph x memgraph x fun -> bool",
|
|
"hlContractMmGraph(_, _, _)",
|
|
"Not yet implemented.",
|
|
"query hlContractMmGraph(memgraphUp, memgraphDown, distanceFunction)"
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
5.4 Operator Instance
|
|
|
|
Here, we create an instance of the operator using a constructor
|
|
of the class ~Operator~ and feeding it with the defined functions.
|
|
For non-overloaded operators, always the selection function
|
|
~Operator::SimpleSelect~ is used.
|
|
|
|
All operators are related to the equal named function of the class
|
|
HubLabelClass.
|
|
The Ooerators just got an additional suffix 'Op'
|
|
|
|
5.4.1 Operator Instance of (1) Persistent Approach
|
|
|
|
*/
|
|
|
|
|
|
|
|
Operator hlCalcRankOp(
|
|
"hlCalcRank", // name of the operator
|
|
hlCalcRankSpec.getStr(), // specification
|
|
hlCalcRankVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlCalcRankTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlOneHopReverseSearchOp(
|
|
"hlOneHopReverseSearch", // name of the operator
|
|
hlOneHopReverseSearchSpec.getStr(), // specification
|
|
hlOneHopReverseSearchVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlOneHopReverseSearchTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlHHopForwardSearchOp(
|
|
"hlHHopForwardSearch", // name of the operator
|
|
hlHHopForwardSearchSpec.getStr(), // specification
|
|
hlHHopForwardSearchVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlHHopForwardSearchTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlForwardSearchGetDistOp(
|
|
"hlForwardSearchGetDist", // name of the operator
|
|
hlForwardSearchGetDistSpec.getStr(), // specification
|
|
hlForwardSearchGetDistVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlForwardSearchGetDistTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlRemoveTFromCurrentWitnessListOp(
|
|
"hlRemoveTFromCurrentWitnessList", // name of the operator
|
|
hlRemoveTFromCurrentWitnessListSpec.getStr(), // specification
|
|
hlRemoveTFromCurrentWitnessListVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlRemoveTFromCurrentWitnessListTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlForwardSearchCheckForWitnessPathOp(
|
|
"hlForwardSearchCheckForWitnessPath", // name of the operatord
|
|
hlForwardSearchCheckForWitnessPathSpec.getStr(), // specification
|
|
hlForwardSearchCheckForWitnessPathVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlForwardSearchCheckForWitnessPathTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlInsertOrUpdateTupleInNotYetVisitedListOp(
|
|
"hlInsertOrUpdateTupleInNotYetVisitedList",
|
|
// name of the operator
|
|
hlInsertOrUpdateTupleInNotYetVisitedListSpec.getStr(), // specification
|
|
hlInsertOrUpdateTupleInNotYetVisitedListVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlInsertOrUpdateTupleInNotYetVisitedListTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlForwardSearchIterativeStepsScanNewVerticesOp(
|
|
"hlForwardSearchIterativeStepsScanNewVertices",
|
|
// name of the operator
|
|
hlForwardSearchIterativeStepsScanNewVerticesSpec.getStr(), // specification
|
|
hlForwardSearchIterativeStepsScanNewVerticesVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlForwardSearchIterativeStepsScanNewVerticesTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlForwardSearchProcessIncomingEdgeIterativeStepsOp(
|
|
"hlForwardSearchProcessIncomingEdgeIterativeSteps",
|
|
// name of the operator
|
|
hlForwardSearchProcessIncomingEdgeIterativeStepsSpec.getStr(),
|
|
// specification
|
|
hlForwardSearchProcessIncomingEdgeIterativeStepsVM,
|
|
// value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlForwardSearchProcessIncomingEdgeIterativeStepsTM
|
|
// type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlForwardSearchProcessIncomingEdgeInitialStepsOp(
|
|
"hlForwardSearchProcessIncomingEdgeInitialSteps",
|
|
// name of the operator
|
|
hlForwardSearchProcessIncomingEdgeInitialStepsSpec.getStr(),
|
|
// specification
|
|
hlForwardSearchProcessIncomingEdgeInitialStepsVM,
|
|
// value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlForwardSearchProcessIncomingEdgeInitialStepsTM
|
|
// type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlForwardSearchCreateAndAppendShortcutsOp(
|
|
"hlForwardSearchCreateAndAppendShortcuts",
|
|
// name of the operator
|
|
hlForwardSearchCreateAndAppendShortcutsSpec.getStr(), // specification
|
|
hlForwardSearchCreateAndAppendShortcutsVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlForwardSearchCreateAndAppendShortcutsTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlForwardSearchProcessIncomingEdgeOp(
|
|
"hlForwardSearchProcessIncomingEdge", // name of the operator
|
|
hlForwardSearchProcessIncomingEdgeSpec.getStr(), // specification
|
|
hlForwardSearchProcessIncomingEdgeVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlForwardSearchProcessIncomingEdgeTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlRemoveContractedEdgesFromEdgesRelationsOp(
|
|
"hlRemoveContractedEdgesFromEdgesRelations",
|
|
// name of the operator
|
|
hlRemoveContractedEdgesFromEdgesRelationsSpec.getStr(), // specification
|
|
hlRemoveContractedEdgesFromEdgesRelationsVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlRemoveContractedEdgesFromEdgesRelationsTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlRemoveParallelEdgesFromEdgesRelationsOp(
|
|
"hlRemoveParallelEdgesFromEdgesRelations",
|
|
// name of the operator
|
|
hlRemoveParallelEdgesFromEdgesRelationsSpec.getStr(), // specification
|
|
hlRemoveParallelEdgesFromEdgesRelationsVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlRemoveParallelEdgesFromEdgesRelationsTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlDoContractionOp(
|
|
"hlDoContraction", // name of the operator
|
|
hlDoContractionSpec.getStr(), // specification
|
|
hlDoContractionVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlDoContractionTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlIterateOverAllNodesByRankAscAndDoContractionOp(
|
|
"hlIterateOverAllNodesByRankAscAndDoContraction",
|
|
// name of the operator
|
|
hlIterateOverAllNodesByRankAscAndDoContractionSpec.getStr(),
|
|
// specification
|
|
hlIterateOverAllNodesByRankAscAndDoContractionVM,
|
|
// value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlIterateOverAllNodesByRankAscAndDoContractionTM
|
|
// type mapping
|
|
);
|
|
|
|
|
|
Operator hlCreateLabelCheckForWitnessScanNewVerticesOp(
|
|
"hlCreateLabelCheckForWitnessScanNewVertices",
|
|
// name of the operator
|
|
hlCreateLabelCheckForWitnessScanNewVerticesSpec.getStr(), // specification
|
|
hlCreateLabelCheckForWitnessScanNewVerticesVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlCreateLabelCheckForWitnessScanNewVerticesTM // type mapping
|
|
);
|
|
|
|
|
|
Operator hlCreateLabelCheckForWitnessOp(
|
|
"hlCreateLabelCheckForWitness", // name of the operator
|
|
hlCreateLabelCheckForWitnessSpec.getStr(), // specification
|
|
hlCreateLabelCheckForWitnessVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlCreateLabelCheckForWitnessTM // type mapping
|
|
);
|
|
|
|
|
|
Operator hlCreateLabelScanNewVerticesOp(
|
|
"hlCreateLabelScanNewVertices", // name of the operator
|
|
hlCreateLabelScanNewVerticesSpec.getStr(), // specification
|
|
hlCreateLabelScanNewVerticesVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlCreateLabelScanNewVerticesTM // type mapping
|
|
);
|
|
|
|
|
|
Operator hlGetRankByIdOp(
|
|
"hlGetRankById", // name of the operator
|
|
hlGetRankByIdSpec.getStr(), // specification
|
|
hlGetRankByIdVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlGetRankByIdTM // type mapping
|
|
);
|
|
|
|
|
|
Operator hlCreateLabelByDijkstraWithStallingOp(
|
|
"hlCreateLabelByDijkstraWithStalling", // name of the operator
|
|
hlCreateLabelByDijkstraWithStallingSpec.getStr(), // specification
|
|
hlCreateLabelByDijkstraWithStallingVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlCreateLabelByDijkstraWithStallingTM // type mapping
|
|
);
|
|
|
|
|
|
Operator hlFillForwardOrReverseLabelOp(
|
|
"hlFillForwardOrReverseLabel", // name of the operator
|
|
hlFillForwardOrReverseLabelSpec.getStr(), // specification
|
|
hlFillForwardOrReverseLabelVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlFillForwardOrReverseLabelTM // type mapping
|
|
);
|
|
|
|
|
|
Operator hlGetPathViaPointsOp(
|
|
"hlGetPathViaPoints", // name of the operator
|
|
hlGetPathViaPointsSpec.getStr(), // specification
|
|
hlGetPathViaPointsVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlGetPathViaPointsTM // type mapping
|
|
);
|
|
|
|
|
|
Operator hlQueryOp(
|
|
"hlQuery", // name of the operator
|
|
hlQuerySpec.getStr(), // specification
|
|
hlQueryVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlQueryTM // type mapping
|
|
);
|
|
|
|
|
|
Operator hlPruneLabelByBootstrappingOp(
|
|
"hlPruneLabelByBootstrapping", // name of the operator
|
|
hlPruneLabelByBootstrappingSpec.getStr(), // specification
|
|
hlPruneLabelByBootstrappingVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlPruneLabelByBootstrappingTM // type mapping
|
|
);
|
|
|
|
|
|
Operator hlReorderLabelsOp(
|
|
"hlReorderLabels", // name of the operator
|
|
hlReorderLabelsSpec.getStr(), // specification
|
|
hlReorderLabelsVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlReorderLabelsTM // type mapping
|
|
);
|
|
|
|
|
|
Operator hlCreateLabelsOp(
|
|
"hlCreateLabels", // name of the operator
|
|
hlCreateLabelsSpec.getStr(), // specification
|
|
hlCreateLabelsVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlCreateLabelsTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
|
|
/*
|
|
5.4.2 Operator Instance of (2) In-Memory Approach
|
|
|
|
*/
|
|
|
|
|
|
Operator hlTransformOrelToHlGraphOp(
|
|
"hlTransformOrelToHlGraph", // name of the operator
|
|
hlTransformOrelToHlGraphSpec.getStr(), // specification
|
|
hlTransformOrelToHlGraphVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlTransformOrelToHlGraphTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlDoContractionOfHlGraphOp(
|
|
"hlDoContractionOfHlGraph", // name of the operator
|
|
hlDoContractionOfHlGraphSpec.getStr(), // specification
|
|
hlDoContractionOfHlGraphVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlDoContractionOfHlGraphTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlDoChSearchInHlGraphOp(
|
|
"hlDoChSearchInHlGraph", // name of the operator
|
|
hlDoChSearchInHlGraphSpec.getStr(), // specification
|
|
hlDoChSearchInHlGraphVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlDoChSearchInHlGraphTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlCalcWeightsOrelOp(
|
|
"hlCalcWeightsOrel", // name of the operator
|
|
hlCalcWeightsOrelSpec.getStr(), // specification
|
|
hlCalcWeightsOrelVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlCalcWeightsOrelTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
Operator hlCreateLabelsFromHlGraphOp(
|
|
"hlCreateLabelsFromHlGraph", // name of the operator
|
|
hlCreateLabelsFromHlGraphSpec.getStr(), // specification
|
|
hlCreateLabelsFromHlGraphVM, // value mapping
|
|
Operator::SimpleSelect, // selection function
|
|
hlCreateLabelsFromHlGraphTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
5.4.2 Operator Instance of (2) In-Memory Approach
|
|
|
|
*/
|
|
|
|
ValueMapping hlContractMmGraphVM[] = {
|
|
hlContractMmGraphVMT<mm2algebra::Mem, mm2algebra::Mem>,
|
|
hlContractMmGraphVMT<mm2algebra::Mem, mm2algebra::MPointer>,
|
|
hlContractMmGraphVMT<mm2algebra::MPointer, mm2algebra::Mem>,
|
|
hlContractMmGraphVMT<mm2algebra::MPointer, mm2algebra::MPointer>,
|
|
};
|
|
|
|
int hlContractMmGraphSelect(ListExpr args){
|
|
int n1 = mm2algebra::Mem::checkType(nl->First(args))?0:2;
|
|
int n2 = mm2algebra::Mem::checkType(nl->Second(args))?0:1;
|
|
return n1+n2;
|
|
}
|
|
|
|
|
|
Operator hlContractMmGraphOp(
|
|
"hlContractMmGraph", // name of the operator
|
|
hlContractMmGraphSpec.getStr(), // specification
|
|
4,
|
|
hlContractMmGraphVM, // value mapping
|
|
hlContractMmGraphSelect, // selection function
|
|
hlContractMmGraphTM // type mapping
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
6 Definition of the Algebra
|
|
|
|
\label{AlgebraDefinition}
|
|
|
|
In this step, a new algebra -- a class derived from the ~Algebra~ class --
|
|
is created. Within the constructor of the algebra, we add the type constructors
|
|
and assign the corresponding kinds to the types.
|
|
Furthermore, all operators are added to the algebra.
|
|
|
|
*/
|
|
|
|
class HubLabelingAlgebra : public Algebra
|
|
{
|
|
public:
|
|
HubLabelingAlgebra() : Algebra()
|
|
{
|
|
|
|
AddTypeConstructor( &HubLabelClassTC );
|
|
HubLabelClassTC.AssociateKind( Kind::SIMPLE() );
|
|
|
|
AddOperator(&hlCalcRankOp);
|
|
AddOperator(&hlOneHopReverseSearchOp);
|
|
AddOperator(&hlHHopForwardSearchOp);
|
|
AddOperator(&hlForwardSearchGetDistOp);
|
|
AddOperator(&hlRemoveTFromCurrentWitnessListOp);
|
|
AddOperator(
|
|
&hlForwardSearchCheckForWitnessPathOp);
|
|
AddOperator(
|
|
&hlInsertOrUpdateTupleInNotYetVisitedListOp);
|
|
AddOperator(
|
|
&hlForwardSearchIterativeStepsScanNewVerticesOp);
|
|
AddOperator(
|
|
&hlForwardSearchProcessIncomingEdgeIterativeStepsOp);
|
|
AddOperator(
|
|
&hlForwardSearchProcessIncomingEdgeInitialStepsOp);
|
|
AddOperator(
|
|
&hlForwardSearchCreateAndAppendShortcutsOp);
|
|
AddOperator(
|
|
&hlForwardSearchProcessIncomingEdgeOp);
|
|
AddOperator(
|
|
&hlRemoveContractedEdgesFromEdgesRelationsOp);
|
|
AddOperator(
|
|
&hlRemoveParallelEdgesFromEdgesRelationsOp);
|
|
AddOperator(&hlDoContractionOp);
|
|
AddOperator(
|
|
&hlIterateOverAllNodesByRankAscAndDoContractionOp);
|
|
AddOperator(
|
|
&hlCreateLabelCheckForWitnessScanNewVerticesOp);
|
|
AddOperator(&hlCreateLabelCheckForWitnessOp);
|
|
AddOperator(&hlCreateLabelScanNewVerticesOp);
|
|
AddOperator(&hlGetRankByIdOp);
|
|
AddOperator(
|
|
&hlCreateLabelByDijkstraWithStallingOp);
|
|
AddOperator(&hlFillForwardOrReverseLabelOp);
|
|
AddOperator(&hlGetPathViaPointsOp);
|
|
AddOperator(&hlQueryOp);
|
|
AddOperator(&hlPruneLabelByBootstrappingOp);
|
|
AddOperator(&hlReorderLabelsOp);
|
|
AddOperator(&hlCreateLabelsOp);
|
|
|
|
|
|
// operator hlContractMmGraph is not implemented
|
|
// completely
|
|
// AddOperator(&hlContractMmGraphOp);
|
|
|
|
|
|
AddOperator(&hlTransformOrelToHlGraphOp);
|
|
AddOperator(&hlDoContractionOfHlGraphOp);
|
|
AddOperator(&hlDoChSearchInHlGraphOp);
|
|
AddOperator(&hlCalcWeightsOrelOp);
|
|
AddOperator(&hlCreateLabelsFromHlGraphOp);
|
|
}
|
|
};
|
|
|
|
|
|
/*
|
|
End of the namespace. The following code cannot be embedded into the
|
|
algebras's namespace. Thus the namespace should end here.
|
|
|
|
*/
|
|
|
|
} // end of namespace
|
|
|
|
|
|
/*
|
|
7 Initialization of the Algebra
|
|
|
|
This piece of code returns a new instance of the algebra.
|
|
|
|
|
|
*/
|
|
extern "C"
|
|
Algebra*
|
|
InitializeHubLabelingAlgebra( NestedList* nlRef,
|
|
QueryProcessor* qpRef )
|
|
{
|
|
return new hublabeling::HubLabelingAlgebra;
|
|
}
|