Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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