88template<
typename TWeight>
102 std::string& error)
override {
104 error =
"The graph is not simple";
108 error =
"The graph is not connected";
112 error =
"The stretch must be >= 1.0";
214 (*m_inSpanner)[e] =
m_E1[e] ||
m_E2[e];
233 for (
int i = 0; i < max; i++) {
236 edge e1 = inPredecessor[v][n];
241 edge e2 = outPredecessor[v][n];
251 logger.
lout() <<
"add unsettled thick edges" << std::endl;
291 int E1amountThick = 0;
292 int E1amountThinNotInE2 = 0;
294 int E2amountThin = 0;
295 int E2amountThickNotInE1 = 0;
296 int edgesCovered = 0;
297 int duplicateCovered = 0;
303 }
else if (!
m_E2[e]) {
304 E1amountThinNotInE2++;
311 }
else if (!
m_E1[e]) {
312 E2amountThickNotInE1++;
323 logger.
lout() <<
"covered: " << edgesCovered <<
", duplicate edges: " << duplicateCovered
325 logger.
lout() <<
"E1: " << E1amount <<
" edges, " << E1amountThick <<
" thick, "
326 << (E1amount - E1amountThick) <<
" thin, " << E1amountThinNotInE2
327 <<
" thin edges not in E2" << std::endl;
328 logger.
lout() <<
"E2: " << E2amount <<
" edges, " << E2amountThin <<
" thin, "
329 << (E2amount - E2amountThin) <<
" thick, " << E2amountThickNotInE1
330 <<
" thick edges not in E1" << std::endl;
332#if defined(OGDF_DEBUG)
334 OGDF_ASSERT((E1amountThick + E2amountThin + E1amountThinNotInE2 + E2amountThickNotInE1)
354 int amountNodesInShortestPaths = 0;
358 if (sd == std::numeric_limits<TWeight>::max()
359 || td == std::numeric_limits<TWeight>::max()) {
366 if (
m_eps.
leq((sd + td), maxDistance)) {
367 amountNodesInShortestPaths++;
390 TWeight currentSpannerDistance =
distance(_spanner, _spannerWeight, u, v, ceil(maxDistance));
391 return m_eps.
leq(currentSpannerDistance, maxDistance);
395 const node t,
int maxLookupDist) {
426 m_osi->messageHandler()->setLogLevel(0);
427 m_osi->setObjSense(1);
430 CoinPackedVector
zero;
439 CoinPackedVector* optConstraint =
new CoinPackedVector;
441 optConstraint->insert(indices[e], 1);
444 m_osi->addRow(*optConstraint,
'L', 0, 0);
450 int amountSolverCalls = 0;
452 if (amountSolverCalls == 0) {
453 m_osi->initialSolve();
461 logger.
lout() << amountSolverCalls <<
". solve... ";
462 if (
m_osi->isProvenOptimal()) {
463 logger.
lout() <<
"-> optimal (" <<
m_osi->getObjValue() <<
")" << std::endl;
474 logger.
lout() <<
"-> Found solution\n" << std::endl;
475 logger.
lout() <<
"solver calls: " << amountSolverCalls << std::endl;
480 logger.
lout() <<
"-> New constraint" << std::endl;
487 }
else if (
m_osi->isProvenPrimalInfeasible()) {
488 logger.
lout() <<
"-> Infeasible" << std::endl;
492 }
else if (
m_osi->isProvenDualInfeasible()) {
496 logger.
lout() <<
"-> No solution found" << std::endl;
510 logger.
lout() <<
" OPT is too large. Abort." << std::endl;
514 logger.
lout() <<
" Set OPT to " <<
m_OPT <<
" (" << std::fixed << std::setprecision(2)
515 << percentage <<
"% of " <<
m_nSquared <<
")" << std::endl;
517 m_osi->setRowBounds(0, 0.0,
532 int amountCoveredEdges = 0;
535 amountCoveredEdges++;
541 bool settlesAllThinEdges =
true;
542 edge unsettledThinEdge =
nullptr;
545 settlesAllThinEdges =
false;
546 unsettledThinEdge = e;
551 if (settlesAllThinEdges) {
562 double rowValue = 0.0;
565 if (antispanner[e]) {
566 rowValue += solution[i];
572 CoinPackedVector* c =
new CoinPackedVector;
574 if (antispanner[e]) {
575 c->insert(indices[e], 1);
578 m_osi->addRow(*c,
'G', 1, 0);
610 bool isInLocalSubgraph = (s_e != std::numeric_limits<TWeight>::max()
611 && e_t != std::numeric_limits<TWeight>::max()
616 if (isInLocalSubgraph && out[e]) {
622 antispanner[e] = isInLocalSubgraph && !out[e];
631 if (!antispanner[e]) {
639 antispanner[e] =
false;
645 antispanner[e] =
true;
662template<
typename TWeight>
Compare floating point numbers with epsilons and integral numbers with normal compare operators.
Includes declaration of graph class.
Declaration of class GraphAttributes which extends a Graph by additional attributes.
Declaration of graph copy classes.
Decralation of GraphElement and GraphList classes.
Contains logging functionality.
Basic module for spanner algorithms.
Basic declarations, included by all source files.
static OsiSolverInterface * createCorrectOsiSolverInterface()
Get a new solver and set its initial log level according to the level of CoinLog.
static constexpr LPSolver whichLPSolver()
Returns the LP-solver used by OGDF.
Dijkstra's single source shortest path algorithm.
void callUnbound(const Graph &G, const EdgeArray< T > &weight, const List< node > &sources, NodeArray< edge > &predecessor, NodeArray< T > &distance, bool directed=false, bool arcsReversed=false)
Calculates, based on the graph G with corresponding edge costs and source nodes, the shortest paths a...
void callBound(const Graph &G, const EdgeArray< T > &weight, const List< node > &sources, NodeArray< edge > &predecessor, NodeArray< T > &distance, bool directed, bool arcsReversed, node target, T maxLength=std::numeric_limits< T >::max())
Calculates, based on the graph G with corresponding edge costs and source nodes, the shortest paths a...
Class for the representation of edges.
node target() const
Returns the target node of the edge.
node source() const
Returns the source node of the edge.
std::enable_if< std::is_integral< T >::value, bool >::type leq(const T &x, const T &y) const
Compare if x is LEQ than y for integral types.
std::enable_if< std::is_integral< T >::value, bool >::type geq(const T &x, const T &y) const
Compare if x is GEQ to y for integral types.
std::enable_if< std::is_integral< T >::value, bool >::type less(const T &x, const T &y) const
Compare if x is LESS than y for integral types.
Stores additional attributes of a graph (like layout information).
bool directed() const
Returns if the graph is directed.
const Graph & constGraph() const
Returns a reference to the associated graph.
node newNode(node vOrig)
Creates a new node in the graph copy with original node vOrig.
Copies of graphs with mapping between nodes and edges.
edge newEdge(edge eOrig)
Creates a new edge in the graph copy with original edge eOrig.
void setOriginalGraph(const Graph *G) override
Re-initializes the copy using G (which might be null), but does not create any nodes or edges.
void delEdge(edge e) override
Removes edge e.
edge copy(edge e) const override
Returns the edge in the graph copy corresponding to e.
Data type for general directed graphs (adjacency list representation).
node chooseNode(std::function< bool(node)> includeNode=[](node) { return true;}, bool isFastTest=true) const
Returns a random node.
int numberOfNodes() const
Returns the number of nodes in the graph.
int numberOfEdges() const
Returns the number of edges in the graph.
internal::GraphObjectContainer< NodeElement > nodes
The container containing all node objects.
internal::GraphObjectContainer< EdgeElement > edges
The container containing all edge objects.
Centralized global and local logging facility working on streams like std::cout.
std::ostream & lout(Level level=Level::Default, bool indent=true) const
stream for logging-output (local)
@ Log
the object is in logging mode, using its own localLogLevel
ReturnType
The return type of a module.
Class for the representation of nodes.
Approximation algorithm for calculating spanners.
void randomizedSelection(const double *fractions, EdgeArray< bool > &out)
void firstPart()
First part of the algorithm: Settle all thick edges.
void printStats(bool assert=false)
EdgeArray< bool > m_isThickEdge
bool secondPart()
The second part: Settling all thin edges.
bool isSettledEdge(const edge e, const GraphCopySimple &_spanner, const EdgeArray< TWeight > &_spannerWeight)
bool isSettledEdge(const edge e)
Shortcut for calling isSettledEdge with m_spanner and the current spanner weights.
const Graph * m_G
const reference to the original graph
int m_OPT
The current guess for our optimal LP value.
SeparationResult
Used to indicate the result of the separation method.
EdgeArray< bool > m_E1
Holds the set E1 from the first part of the algorithm.
EdgeArray< bool > m_E2
Holds the set E2 from the second part of the algorithm.
NodeArray< NodeArray< TWeight > > m_outDistance
m_outDistance[v][w]: distance from v in a v-rooted out-arborescense to w
int m_thickEdgeNodeAmountLimit
n/beta
EdgeArray< TWeight > m_spannerWeight
weights for m_spanner Caches, if an edge is thick (or thin).
SeparationResult separation(const double *solution, const EdgeArray< int > &indices)
OsiSolverInterface * m_osi
the solver.
virtual void init(const GraphAttributes &GA, double stretch, GraphCopySimple &spanner, EdgeArray< bool > &inSpanner) override
Initializes members and create an empty spanner.
void outArborescence(const GraphAttributes &GA, node root, NodeArray< edge > &predecessor, NodeArray< TWeight > &distance)
Calculates an out-arborescense rooted at root.
virtual SpannerModule< TWeight >::ReturnType execute() override
Executes the core algorithm.
NodeArray< NodeArray< TWeight > > m_inDistance
m_inDistance[v][w]: distance from v in a v-rooted in-arborescense to w
void addUnsettledThickEdges()
void inArborescence(const GraphAttributes &GA, node root, NodeArray< edge > &predecessor, NodeArray< TWeight > &distance)
Calculates an in-arborescense rooted at root.
void addEdgeToSpanner(edge e)
Add an edge to the spanner.
virtual bool preconditionsOk(const GraphAttributes &GA, double stretch, std::string &error) override
bool setOpt(int opt)
Set a new value for m_OPT.
bool _isThickEdge(edge e)
Actually calculates whether e is thick or not.
std::vector< CoinPackedVector * > m_constraints
Holds all constraints so they can be freed at destruction.
EdgeArray< TWeight > m_weight
weights of each edge from m_G
void calculateThickEdges()
void createAntispanner(const edge unsettledThinEdge, const EdgeArray< bool > &out, EdgeArray< bool > &antispanner)
void resetLP()
Resets the LP defining variables.
double m_sqrtlog
sqrt(n) * ln(n)
TWeight distance(const GraphCopySimple &G, const EdgeArray< TWeight > &weights, const node s, const node t, int maxLookupDist)
Interface for spanner algorithms.
void assertTimeLeft()
Assert, that time is left.
virtual void init(const GraphAttributes &GA, double stretch, GraphCopySimple &spanner, EdgeArray< bool > &inSpanner)
Initializes members and create an empty spanner.
const GraphAttributes * m_GA
EdgeArray< bool > * m_inSpanner
static TWeight getWeight(const GraphAttributes &GA, edge e)
GraphCopySimple * m_spanner
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition of ogdf::CoinManager.
Implementation of Dijkstra's single source shortest path algorithm.
bool isConnected(const Graph &G)
Returns true iff G is connected.
bool isSimple(const Graph &G)
Returns true iff G contains neither self-loops nor parallel edges.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
double randomDouble(double low, double high)
Returns a random double value from the interval [low, high).
The namespace for all OGDF objects.
Declaration of simple graph algorithms.