Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

SpannerBerman.h
Go to the documentation of this file.
1 
32 #pragma once
33 
34 #include <ogdf/basic/EpsilonTest.h>
35 #include <ogdf/basic/Graph.h>
37 #include <ogdf/basic/GraphCopy.h>
38 #include <ogdf/basic/GraphList.h>
39 #include <ogdf/basic/Logger.h>
40 #include <ogdf/basic/basic.h>
42 #include <ogdf/graphalg/Dijkstra.h>
44 
45 #include <ogdf/external/coin.h>
46 
47 #include <cmath>
48 #include <iomanip>
49 #include <limits>
50 #include <ostream>
51 #include <string>
52 #include <vector>
53 
54 namespace ogdf {
55 
88 template<typename TWeight>
89 class SpannerBerman : public SpannerModule<TWeight> {
90 public:
91  static Logger logger;
92 
94  m_OPT = 0;
95  m_osi = nullptr;
96  }
97 
98  virtual ~SpannerBerman() { resetLP(); }
99 
101  virtual bool preconditionsOk(const GraphAttributes& GA, double stretch,
102  std::string& error) override {
103  if (!isSimple(GA.constGraph())) {
104  error = "The graph is not simple";
105  return false;
106  }
107  if (!isConnected(GA.constGraph())) {
108  error = "The graph is not connected";
109  return false;
110  }
111  if (stretch < 1.0) {
112  error = "The stretch must be >= 1.0";
113  return false;
114  }
115  return true;
116  }
117 
118 private:
123 
124  const Graph* m_G;
130 
131  // Some precalculated values that are needed all over the place.
133  double m_beta;
134  double m_sqrtlog;
136 
139 
142 
143  // Solving the LP
144  OsiSolverInterface* m_osi;
145  std::vector<CoinPackedVector*> m_constraints;
146  int m_OPT;
147 
149 
150  inline bool isThinEdge(edge e) { return !m_isThickEdge(e); }
151 
152  inline bool isThickEdge(edge e) { return m_isThickEdge(e); }
153 
159  void resetLP() {
160  for (auto c : m_constraints) {
161  delete c;
162  }
163  m_constraints.clear();
164 
165  delete m_osi;
166  m_osi = nullptr;
167  }
168 
170  virtual void init(const GraphAttributes& GA, double stretch, GraphCopySimple& spanner,
171  EdgeArray<bool>& inSpanner) override {
172  resetLP();
173  SpannerModule<TWeight>::init(GA, stretch, spanner, inSpanner);
174 
175  m_G = &GA.constGraph();
176  m_weight.init(*m_G);
177  for (edge e : m_G->edges) {
178  m_weight[e] = getWeight(*m_GA, e);
179  }
180  m_spannerWeight.init(*m_spanner);
181  m_isThickEdge.init(*m_G, false);
182 
184  m_beta = sqrt(m_G->numberOfNodes()),
186  m_sqrtlog = sqrt(m_G->numberOfNodes()) * log(m_G->numberOfNodes());
187 
188  m_E1.init(*m_G, false);
189  m_E2.init(*m_G, false);
190 
191  m_inDistance.init(*m_G);
192  m_outDistance.init(*m_G);
193  }
194 
196  virtual typename SpannerModule<TWeight>::ReturnType execute() override {
197  if (m_G->numberOfNodes() == 0 || m_G->numberOfEdges() == 0) {
199  }
200  firstPart();
201  printStats();
202 
203  logger.lout() << "\n2. Part\n" << std::endl;
204  bool ok = secondPart();
205 
206  if (!ok) {
208  }
209 
210  printStats(true);
211 
212  // Fill m_inSpanner since only E1, E2 and m_spanner are correctly filled.
213  for (edge e : m_G->edges) {
214  (*m_inSpanner)[e] = m_E1[e] || m_E2[e];
215  }
217  }
218 
222  void firstPart() {
223  NodeArray<NodeArray<edge>> inPredecessor(*m_G);
224  NodeArray<NodeArray<edge>> outPredecessor(*m_G);
225  for (node n : m_G->nodes) {
226  inArborescence(*m_GA, n, inPredecessor[n], m_inDistance[n]);
227  outArborescence(*m_GA, n, outPredecessor[n], m_outDistance[n]);
228  assertTimeLeft();
229  }
230 
231  int max = ceil(m_beta * log(m_G->numberOfNodes())); // log is ln
232  logger.lout() << "max=" << max << std::endl;
233  for (int i = 0; i < max; i++) {
234  node v = m_G->chooseNode();
235  for (node n : m_G->nodes) {
236  edge e1 = inPredecessor[v][n];
237  if (e1) {
238  addEdgeToSpanner(e1);
239  }
240 
241  edge e2 = outPredecessor[v][n];
242  if (e2) {
243  addEdgeToSpanner(e2);
244  }
245  }
246  }
247  assertTimeLeft();
248  logger.lout() << "thickEdgeNodeAmountLimit=" << m_thickEdgeNodeAmountLimit << std::endl;
249  printStats();
250 
251  logger.lout() << "add unsettled thick edges" << std::endl;
254  }
255 
259  void inArborescence(const GraphAttributes& GA, node root, NodeArray<edge>& predecessor,
261  Dijkstra<TWeight> dijkstra;
262  dijkstra.callUnbound(*m_G, m_weight, root, predecessor, distance, true, true);
263  }
264 
268  void outArborescence(const GraphAttributes& GA, node root, NodeArray<edge>& predecessor,
270  Dijkstra<TWeight> dijkstra;
271  dijkstra.callUnbound(*m_G, m_weight, root, predecessor, distance, true, false);
272  }
273 
278  if (!m_E1[e]) {
279  m_E1[e] = true;
280  m_spanner->newEdge(e);
282  }
283  }
284 
285  void printStats(bool assert = false) {
286  logger.lout() << "\nStats:" << std::endl;
287  logger.lout() << m_spanner->numberOfEdges() << " covered of " << m_G->numberOfEdges()
288  << std::endl;
289 
290  int E1amount = 0;
291  int E1amountThick = 0;
292  int E1amountThinNotInE2 = 0;
293  int E2amount = 0;
294  int E2amountThin = 0;
295  int E2amountThickNotInE1 = 0;
296  int edgesCovered = 0;
297  int duplicateCovered = 0;
298  for (edge e : m_G->edges) {
299  if (m_E1[e]) {
300  E1amount++;
301  if (isThickEdge(e)) {
302  E1amountThick++;
303  } else if (!m_E2[e]) {
304  E1amountThinNotInE2++;
305  }
306  }
307  if (m_E2[e]) {
308  E2amount++;
309  if (isThinEdge(e)) {
310  E2amountThin++;
311  } else if (!m_E1[e]) {
312  E2amountThickNotInE1++;
313  }
314  }
315  if (m_E1[e] || m_E2[e]) {
316  edgesCovered++;
317  }
318  if (m_E1[e] && m_E2[e]) {
319  duplicateCovered++;
320  }
321  }
322 
323  logger.lout() << "covered: " << edgesCovered << ", duplicate edges: " << duplicateCovered
324  << std::endl;
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;
331 
332 #if defined(OGDF_DEBUG)
333  if (assert) {
334  OGDF_ASSERT((E1amountThick + E2amountThin + E1amountThinNotInE2 + E2amountThickNotInE1)
335  == m_spanner->numberOfEdges());
336  }
337 #endif
338 
339  OGDF_ASSERT(edgesCovered == m_spanner->numberOfEdges());
340  }
341 
343  for (edge e : m_G->edges) {
344  m_isThickEdge[e] = _isThickEdge(e);
345  }
346  }
347 
351  bool _isThickEdge(edge e) {
352  const TWeight maxDistance = m_stretch * m_weight[e];
353 
354  int amountNodesInShortestPaths = 0;
355  for (node n : m_G->nodes) {
356  TWeight sd = m_outDistance[e->source()][n];
357  TWeight td = m_inDistance[e->target()][n];
358  if (sd == std::numeric_limits<TWeight>::max()
359  || td == std::numeric_limits<TWeight>::max()) {
360  continue;
361  }
362 
363  OGDF_ASSERT(m_eps.geq(sd + td, static_cast<TWeight>(0)));
364  OGDF_ASSERT(m_eps.less(sd + td, std::numeric_limits<TWeight>::max()));
365 
366  if (m_eps.leq((sd + td), maxDistance)) {
367  amountNodesInShortestPaths++;
368  }
369 
370  if (amountNodesInShortestPaths >= m_thickEdgeNodeAmountLimit) {
371  return true;
372  }
373  }
374  return false;
375  }
376 
380  bool isSettledEdge(const edge e) { return isSettledEdge(e, *m_spanner, m_spannerWeight); }
381 
385  bool isSettledEdge(const edge e, const GraphCopySimple& _spanner,
386  const EdgeArray<TWeight>& _spannerWeight) {
387  const TWeight maxDistance = m_stretch * m_weight[e];
388  node u = _spanner.copy(e->source());
389  node v = _spanner.copy(e->target());
390  TWeight currentSpannerDistance = distance(_spanner, _spannerWeight, u, v, ceil(maxDistance));
391  return m_eps.leq(currentSpannerDistance, maxDistance);
392  }
393 
394  TWeight distance(const GraphCopySimple& G, const EdgeArray<TWeight>& weights, const node s,
395  const node t, int maxLookupDist) {
396  NodeArray<TWeight> distances;
397  NodeArray<edge> predecessor;
398  Dijkstra<TWeight> dijkstra;
399  dijkstra.callBound(G, weights, s, predecessor, distances, m_GA->directed(),
400  false, // arcs are not reversed
401  t, maxLookupDist);
402  return distances[t];
403  }
404 
406  for (edge e : m_G->edges) {
407  if (m_E1[e]) {
408  continue;
409  }
410 
411  if (isThickEdge(e)) {
412  if (!isSettledEdge(e)) {
413  addEdgeToSpanner(e);
414  }
415  assertTimeLeft();
416  }
417  }
418  }
419 
423  bool secondPart() {
424  logger.lout() << "Using LP-Solver: " << Configuration::whichLPSolver() << std::endl;
426  m_osi->messageHandler()->setLogLevel(0); // 0=nothing .. 4=verbose
427  m_osi->setObjSense(1); // minimize
428 
429  // One column per edge (x_e)
430  CoinPackedVector zero;
431  EdgeArray<int> indices(*m_G);
432  int i = 0;
433  for (edge e : m_G->edges) {
434  m_osi->addCol(zero, 0, 1, 1); // vec, lower, upper, objective
435  indices[e] = i++;
436  }
437 
438 
439  CoinPackedVector* optConstraint = new CoinPackedVector;
440  for (edge e : m_G->edges) {
441  optConstraint->insert(indices[e], 1);
442  }
443  // sense: 'E' == 'G' >= 'L' <=
444  m_osi->addRow(*optConstraint, 'L', 0, 0); // constraint, sense, rhs (will be set below), range
445  m_constraints.push_back(optConstraint);
446 
447  // Set the initial value of the OPT constraint rhs to n-1
448  setOpt(m_G->numberOfNodes() - 1);
449 
450  int amountSolverCalls = 0;
451  while (true) {
452  if (amountSolverCalls == 0) {
453  m_osi->initialSolve();
454  } else {
455  m_osi->resolve();
456  }
457  amountSolverCalls++;
458 
459  assertTimeLeft();
460 
461  logger.lout() << amountSolverCalls << ". solve... ";
462  if (m_osi->isProvenOptimal()) {
463  logger.lout() << "-> optimal (" << m_osi->getObjValue() << ")" << std::endl;
464  logger.lout() << " separation... ";
465  SeparationResult result = separation(m_osi->getColSolution(), indices);
466 
467  if (result == SeparationResult::Solution) {
468  for (edge e : m_G->edges) {
469  if (m_E2[e] && !m_E1[e]) {
470  m_spanner->newEdge(e);
472  }
473  }
474  logger.lout() << "-> Found solution\n" << std::endl;
475  logger.lout() << "solver calls: " << amountSolverCalls << std::endl;
476  logger.lout() << "cols: " << m_osi->getNumCols() << std::endl;
477  logger.lout() << "rows: " << m_osi->getNumRows() << std::endl;
478  return true;
479  } else if (result == SeparationResult::NewConstraint) {
480  logger.lout() << "-> New constraint" << std::endl;
481  } else { // Fail
482  logger.lout() << "-> Failed" << std::endl;
483  if (!setOpt(m_OPT + 1)) {
484  return false;
485  }
486  }
487  } else if (m_osi->isProvenPrimalInfeasible()) {
488  logger.lout() << "-> Infeasible" << std::endl;
489  if (!setOpt(m_OPT + 1)) {
490  return false;
491  }
492  } else if (m_osi->isProvenDualInfeasible()) {
493  logger.lout() << "-> Unbounded" << std::endl;
494  return false;
495  } else {
496  logger.lout() << "-> No solution found" << std::endl;
497  return false;
498  }
499  };
500  }
501 
507  bool setOpt(int opt) {
508  m_OPT = opt;
509  if (m_OPT > m_nSquared) {
510  logger.lout() << " OPT is too large. Abort." << std::endl;
511  return false;
512  }
513  float percentage = static_cast<float>(m_OPT) / m_nSquared * 100.0;
514  logger.lout() << " Set OPT to " << m_OPT << " (" << std::fixed << std::setprecision(2)
515  << percentage << "% of " << m_nSquared << ")" << std::endl;
516 
517  m_osi->setRowBounds(0, 0.0,
518  m_OPT); // this is the opt constraint; it is 0 <= sum(x_e) <= m_OPT
519  return true;
520  }
521 
522  SeparationResult separation(const double* solution, const EdgeArray<int>& indices) {
523  EdgeArray<bool> out(*m_G, false);
524  randomizedSelection(solution, out);
525 
527  copy.setOriginalGraph(*m_G);
528  for (node n : m_G->nodes) {
529  copy.newNode(n);
530  }
531  EdgeArray<TWeight> copyWeight(copy);
532  int amountCoveredEdges = 0;
533  for (edge e : m_G->edges) {
534  if (out[e]) {
535  amountCoveredEdges++;
536  copy.newEdge(e);
537  copyWeight[copy.copy(e)] = m_weight[e];
538  }
539  }
540 
541  bool settlesAllThinEdges = true;
542  edge unsettledThinEdge = nullptr;
543  for (edge e : m_G->edges) {
544  if (isThinEdge(e) && !isSettledEdge(e, copy, copyWeight)) {
545  settlesAllThinEdges = false;
546  unsettledThinEdge = e;
547  break;
548  }
549  }
550 
551  if (settlesAllThinEdges) {
552  if (amountCoveredEdges <= ceil(2.0 * m_OPT * m_sqrtlog)) {
553  m_E2 = out;
555  } else {
556  return SeparationResult::Fail;
557  }
558  } else {
559  EdgeArray<bool> antispanner(*m_G, false);
560  createAntispanner(unsettledThinEdge, out, antispanner);
561 
562  double rowValue = 0.0;
563  int i = 0;
564  for (edge e : m_G->edges) {
565  if (antispanner[e]) {
566  rowValue += solution[i];
567  }
568  i++;
569  }
570  if (m_eps.less(rowValue, 1.0)) {
571  // create new constraint
572  CoinPackedVector* c = new CoinPackedVector;
573  for (edge e : m_G->edges) {
574  if (antispanner[e]) {
575  c->insert(indices[e], 1);
576  }
577  }
578  m_osi->addRow(*c, 'G', 1, 0);
579  m_constraints.push_back(c);
581  } else {
582  return SeparationResult::Fail;
583  }
584  }
585  }
586 
587  void randomizedSelection(const double* fractions, EdgeArray<bool>& out) {
588  int i = 0;
589  for (edge e : m_G->edges) {
590  double p = m_sqrtlog * fractions[i++]; // P may not be limited to 1: if it is >1 the
591  // result will always be true, which is ok.
592  out[e] = randomDouble(0.0, 1.0) <= p;
593  }
594  }
595 
596  void createAntispanner(const edge unsettledThinEdge, const EdgeArray<bool>& out,
597  EdgeArray<bool>& antispanner) {
599  copy.setOriginalGraph(*m_G);
600  for (node n : m_G->nodes) {
601  copy.newNode(n);
602  }
603  EdgeArray<TWeight> copyWeight(copy);
604 
605  const TWeight maxDistance = m_stretch * m_weight[unsettledThinEdge];
606  for (edge e : m_G->edges) {
607  // s->e->t
608  TWeight s_e = m_outDistance[unsettledThinEdge->source()][e->source()];
609  TWeight e_t = m_inDistance[unsettledThinEdge->target()][e->target()];
610  bool isInLocalSubgraph = (s_e != std::numeric_limits<TWeight>::max()
611  && e_t != std::numeric_limits<TWeight>::max()
612  && m_eps.leq(s_e + m_weight[e] + e_t, maxDistance));
613 
614  // Graph to maximize is E_st\(E_st\E2) = E_st intersection E2
615  // intersection[e] = isInLocalSubgraph && out[e];
616  if (isInLocalSubgraph && out[e]) {
617  copy.newEdge(e);
618  copyWeight[copy.copy(e)] = m_weight[e];
619  }
620 
621  // e in antispanner <=> e in E_st and not in E2 (=out)
622  antispanner[e] = isInLocalSubgraph && !out[e];
623  }
624  assertTimeLeft();
625 
626  // minimize antispanner
627  bool changed;
628  do {
629  changed = false;
630  for (edge e : m_G->edges) {
631  if (!antispanner[e]) {
632  continue;
633  }
634 
635  // try to remove e and check, if still no path <=stretch*max exists
636  // -> removing e from antispanner is equivalent to adding e to the graph
637  copy.newEdge(e);
638  copyWeight[copy.copy(e)] = m_weight[e];
639  antispanner[e] = false;
640 
641  if (!isSettledEdge(unsettledThinEdge, copy, copyWeight)) {
642  // we've found an unnecessary edge.
643  changed = true;
644  } else {
645  antispanner[e] = true;
646  copy.delEdge(copy.copy(e));
647  }
648  }
649 
650  assertTimeLeft();
651  } while (changed);
652  }
653 
660 };
661 
662 template<typename TWeight>
664  Logger::Level::High); // do not log by default
665 
666 }
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
ogdf::GraphAttributes
Stores additional attributes of a graph (like layout information).
Definition: GraphAttributes.h:72
GraphAttributes.h
Declaration of class GraphAttributes which extends a Graph by additional attributes.
EpsilonTest.h
Compare floating point numbers with epsilons and integral numbers with normal compare operators.
Graph.h
Includes declaration of graph class.
ogdf::EpsilonTest
Definition: EpsilonTest.h:39
ogdf::CoinManager::createCorrectOsiSolverInterface
static OsiSolverInterface * createCorrectOsiSolverInterface()
Get a new solver and set its initial log level according to the level of CoinLog.
Definition: coin.h:55
ogdf::SpannerBerman::m_spannerWeight
EdgeArray< TWeight > m_spannerWeight
weights for m_spanner Caches, if an edge is thick (or thin).
Definition: SpannerBerman.h:126
ogdf::SpannerBerman::m_thickEdgeNodeAmountLimit
int m_thickEdgeNodeAmountLimit
n/beta
Definition: SpannerBerman.h:135
ogdf::GraphCopySimple::copy
edge copy(edge e) const override
Returns the edge in the graph copy corresponding to e.
Definition: GraphCopy.h:295
ogdf::SpannerModule::m_spanner
GraphCopySimple * m_spanner
Definition: SpannerModule.h:136
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
ogdf::SpannerBerman::m_nSquared
int m_nSquared
n^2
Definition: SpannerBerman.h:132
ogdf::SpannerBerman::firstPart
void firstPart()
First part of the algorithm: Settle all thick edges.
Definition: SpannerBerman.h:222
ogdf::SpannerBerman::randomizedSelection
void randomizedSelection(const double *fractions, EdgeArray< bool > &out)
Definition: SpannerBerman.h:587
ogdf::SpannerBerman::m_weight
EdgeArray< TWeight > m_weight
weights of each edge from m_G
Definition: SpannerBerman.h:125
ogdf::SpannerBerman::m_sqrtlog
double m_sqrtlog
sqrt(n) * ln(n)
Definition: SpannerBerman.h:134
ogdf::SpannerModule::init
virtual void init(const GraphAttributes &GA, double stretch, GraphCopySimple &spanner, EdgeArray< bool > &inSpanner)
Initializes members and create an empty spanner.
Definition: SpannerModule.h:142
ogdf::SpannerBerman::SeparationResult::Fail
@ Fail
ogdf::SpannerBerman::printStats
void printStats(bool assert=false)
Definition: SpannerBerman.h:285
ogdf::SpannerBerman::SeparationResult
SeparationResult
Used to indicate the result of the separation method.
Definition: SpannerBerman.h:122
ogdf::SpannerBerman::init
virtual void init(const GraphAttributes &GA, double stretch, GraphCopySimple &spanner, EdgeArray< bool > &inSpanner) override
Initializes members and create an empty spanner.
Definition: SpannerBerman.h:170
ogdf::SpannerBerman::~SpannerBerman
virtual ~SpannerBerman()
Definition: SpannerBerman.h:98
ogdf::Dijkstra::callUnbound
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...
Definition: Dijkstra.h:77
ogdf::SpannerBerman::SeparationResult::NewConstraint
@ NewConstraint
ogdf::SpannerModule::assertTimeLeft
void assertTimeLeft()
Assert, that time is left.
Definition: SpannerModule.h:178
ogdf::SpannerBerman::isThickEdge
bool isThickEdge(edge e)
Definition: SpannerBerman.h:152
ogdf::SpannerBerman::m_isThickEdge
EdgeArray< bool > m_isThickEdge
Definition: SpannerBerman.h:129
ogdf::SpannerBerman::m_E1
EdgeArray< bool > m_E1
Holds the set E1 from the first part of the algorithm.
Definition: SpannerBerman.h:137
ogdf::SpannerBerman::secondPart
bool secondPart()
The second part: Settling all thin edges.
Definition: SpannerBerman.h:423
ogdf::GraphCopySimple
Copies of graphs with mapping between nodes and edges.
Definition: GraphCopy.h:261
ogdf::isConnected
bool isConnected(const Graph &G)
Returns true iff G is connected.
ogdf::Configuration::whichLPSolver
static constexpr LPSolver whichLPSolver()
Returns the LP-solver used by OGDF.
Definition: config.h:335
ogdf::GraphAttributes::directed
bool directed() const
Returns if the graph is directed.
Definition: GraphAttributes.h:232
ogdf::SpannerBerman::m_constraints
std::vector< CoinPackedVector * > m_constraints
Holds all constraints so they can be freed at destruction.
Definition: SpannerBerman.h:145
ogdf::GraphAttributes::constGraph
const Graph & constGraph() const
Returns a reference to the associated graph.
Definition: GraphAttributes.h:223
ogdf::SpannerBerman::m_outDistance
NodeArray< NodeArray< TWeight > > m_outDistance
m_outDistance[v][w]: distance from v in a v-rooted out-arborescense to w
Definition: SpannerBerman.h:141
ogdf::Dijkstra::callBound
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...
Definition: Dijkstra.h:145
SpannerModule.h
Basic module for spanner algorithms.
ogdf::SpannerBerman::m_inDistance
NodeArray< NodeArray< TWeight > > m_inDistance
m_inDistance[v][w]: distance from v in a v-rooted in-arborescense to w
Definition: SpannerBerman.h:140
ogdf::EpsilonTest::less
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.
Definition: EpsilonTest.h:55
Logger.h
Contains logging functionality.
ogdf::SpannerBerman::execute
virtual SpannerModule< TWeight >::ReturnType execute() override
Executes the core algorithm.
Definition: SpannerBerman.h:196
ogdf::SpannerBerman::m_E2
EdgeArray< bool > m_E2
Holds the set E2 from the second part of the algorithm.
Definition: SpannerBerman.h:138
coin.h
Definition of ogdf::CoinManager.
ogdf::Dijkstra
Dijkstra's single source shortest path algorithm.
Definition: Dijkstra.h:60
ogdf::SpannerBerman::resetLP
void resetLP()
Resets the LP defining variables.
Definition: SpannerBerman.h:159
ogdf::Logger::LogMode::Log
@ Log
the object is in logging mode, using its own localLogLevel
ogdf::SpannerBerman::m_OPT
int m_OPT
The current guess for our optimal LP value.
Definition: SpannerBerman.h:146
ogdf::Graph::nodes
internal::GraphObjectContainer< NodeElement > nodes
The container containing all node objects.
Definition: Graph_d.h:932
Minisat::Internal::copy
static void copy(const T &from, T &to)
Definition: Alg.h:61
ogdf::Graph::numberOfEdges
int numberOfEdges() const
Returns the number of edges in the graph.
Definition: Graph_d.h:985
ogdf::SpannerBerman::m_osi
OsiSolverInterface * m_osi
the solver.
Definition: SpannerBerman.h:144
ogdf::SpannerBerman::SeparationResult::Solution
@ Solution
ogdf::Graph::numberOfNodes
int numberOfNodes() const
Returns the number of nodes in the graph.
Definition: Graph_d.h:982
ogdf::SpannerBerman::isSettledEdge
bool isSettledEdge(const edge e)
Shortcut for calling isSettledEdge with m_spanner and the current spanner weights.
Definition: SpannerBerman.h:380
GraphList.h
Decralation of GraphElement and GraphList classes.
ogdf::MeasureEnum::log
@ log
ogdf::SpannerBerman::m_eps
EpsilonTest m_eps
Definition: SpannerBerman.h:148
ogdf::SpannerBerman::calculateThickEdges
void calculateThickEdges()
Definition: SpannerBerman.h:342
ogdf::EdgeElement::source
node source() const
Returns the source node of the edge.
Definition: Graph_d.h:398
GraphCopy.h
Declaration of graph copy classes.
ogdf::SpannerModule::m_stretch
double m_stretch
Definition: SpannerModule.h:135
ogdf::internal::GraphRegisteredArray
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition: Graph_d.h:658
ogdf::Graph
Data type for general directed graphs (adjacency list representation).
Definition: Graph_d.h:869
ogdf::SpannerModule
Interface for spanner algorithms.
Definition: SpannerModule.h:63
ogdf::Logger::Level::High
@ High
ogdf::SpannerBerman::addEdgeToSpanner
void addEdgeToSpanner(edge e)
Add an edge to the spanner.
Definition: SpannerBerman.h:277
ogdf::SpannerBerman::SpannerBerman
SpannerBerman()
Definition: SpannerBerman.h:93
ogdf::SpannerBerman::logger
static Logger logger
Definition: SpannerBerman.h:91
ogdf::EpsilonTest::leq
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.
Definition: EpsilonTest.h:81
ogdf::SpannerBerman::distance
TWeight distance(const GraphCopySimple &G, const EdgeArray< TWeight > &weights, const node s, const node t, int maxLookupDist)
Definition: SpannerBerman.h:394
ogdf::SpannerBerman
Approximation algorithm for calculating spanners.
Definition: SpannerBerman.h:89
ogdf::Graph::edges
internal::GraphObjectContainer< EdgeElement > edges
The container containing all edge objects.
Definition: Graph_d.h:935
ogdf::SpannerBerman::createAntispanner
void createAntispanner(const edge unsettledThinEdge, const EdgeArray< bool > &out, EdgeArray< bool > &antispanner)
Definition: SpannerBerman.h:596
basic.h
Basic declarations, included by all source files.
ogdf::SpannerModule::m_GA
const GraphAttributes * m_GA
Definition: SpannerModule.h:134
ogdf::SpannerBerman::preconditionsOk
virtual bool preconditionsOk(const GraphAttributes &GA, double stretch, std::string &error) override
Definition: SpannerBerman.h:101
ogdf::SpannerBerman::addUnsettledThickEdges
void addUnsettledThickEdges()
Definition: SpannerBerman.h:405
ogdf::EdgeElement
Class for the representation of edges.
Definition: Graph_d.h:363
Dijkstra.h
Implementation of Dijkstra's single source shortest path algorithm.
ogdf::SpannerBerman::isSettledEdge
bool isSettledEdge(const edge e, const GraphCopySimple &_spanner, const EdgeArray< TWeight > &_spannerWeight)
Definition: SpannerBerman.h:385
ogdf::SpannerBerman::isThinEdge
bool isThinEdge(edge e)
Definition: SpannerBerman.h:150
ogdf::EpsilonTest::geq
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.
Definition: EpsilonTest.h:133
ogdf::Logger
Centralized global and local logging facility working on streams like std::cout.
Definition: Logger.h:102
ogdf::SpannerBerman::setOpt
bool setOpt(int opt)
Set a new value for m_OPT.
Definition: SpannerBerman.h:507
ogdf::EdgeElement::target
node target() const
Returns the target node of the edge.
Definition: Graph_d.h:401
ogdf::MeasureEnum::zero
@ zero
ogdf::Module::ReturnType
ReturnType
The return type of a module.
Definition: Module.h:52
ogdf::SpannerBerman::inArborescence
void inArborescence(const GraphAttributes &GA, node root, NodeArray< edge > &predecessor, NodeArray< TWeight > &distance)
Calculates an in-arborescense rooted at root.
Definition: SpannerBerman.h:259
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:240
ogdf::GraphCopySimple::newEdge
edge newEdge(edge eOrig)
Creates a new edge in the graph copy with original edge eOrig.
Definition: GraphCopy.h:321
ogdf::isSimple
bool isSimple(const Graph &G)
Returns true iff G contains neither self-loops nor parallel edges.
Definition: simple_graph_alg.h:402
ogdf::Graph::chooseNode
node chooseNode(std::function< bool(node)> includeNode=[](node) { return true;}, bool isFastTest=true) const
Returns a random node.
simple_graph_alg.h
Declaration of simple graph algorithms.
ogdf::SpannerBerman::m_beta
double m_beta
sqrt(n)
Definition: SpannerBerman.h:133
ogdf::SpannerBerman::_isThickEdge
bool _isThickEdge(edge e)
Actually calculates whether e is thick or not.
Definition: SpannerBerman.h:351
ogdf::SpannerBerman::outArborescence
void outArborescence(const GraphAttributes &GA, node root, NodeArray< edge > &predecessor, NodeArray< TWeight > &distance)
Calculates an out-arborescense rooted at root.
Definition: SpannerBerman.h:268
ogdf::randomDouble
double randomDouble(double low, double high)
Returns a random double value from the interval [low, high).
ogdf::SpannerBerman::m_G
const Graph * m_G
const reference to the original graph
Definition: SpannerBerman.h:124
ogdf::internal::EdgeArrayBase2
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition: Graph_d.h:716
ogdf::SpannerBerman::separation
SeparationResult separation(const double *solution, const EdgeArray< int > &indices)
Definition: SpannerBerman.h:522
ogdf::Logger::lout
std::ostream & lout(Level level=Level::Default, bool indent=true) const
stream for logging-output (local)
Definition: Logger.h:160
ogdf::SpannerModule::getWeight
static TWeight getWeight(const GraphAttributes &GA, edge e)