3#include "elementa/license.inc"
4#include "elementa/checks.inc"
6#ifndef ELEMENTA_ADTS_GRAPH_SEARCH_H
7#define ELEMENTA_ADTS_GRAPH_SEARCH_H
66template <
class Vertex,
class Edge, GPathKind KIND>
98 bool detectcycles =
true,
114 bool found(
void)
const noexcept {
return(!isend_); }
117 bool next(
void) {
return(isend_ ?
false :
137 void checkEnd(
const std::string & place)
const;
142 void doBacktrack(
void);
181template <
class Vertex,
class Edge,
class Weight =
double>
199 trivial_edge_weight<Vertex,Edge>,
218 bool filled(
void)
const noexcept {
return(distMatrix_ !=
nullptr); }
249 Weight * distMatrix_;
250 std::vector<bool> infs_;
252 typename Gr::MapOfVItPos * posmap_;
257 {
return(
static_cast<size_t>(i) *
static_cast<size_t>(V_) +
258 static_cast<size_t>(j)); }
262 void checkCalcs(
void)
const
283template <
class Vertex,
class Edge, GPathKind KIND>
290 g_{&gr},vit0_{vit0},vit1_{vit1},
291 detectcycles_{detectcycles},
292 epred_{&epred},isend_{false}
305 ELE_CODE_TRACE({},
"isend_: " << isend_);
308template <
class Vertex,
class Edge, GPathKind KIND>
310checkEnd(
const std::string & place)
const
318template <
class Vertex,
class Edge, GPathKind KIND>
319bool AllPathsVertices<Vertex,Edge,KIND>::isACycle
320 (
const typename GraphType::viterator & v,
321 GPathKindType<GPathKind::kVertexPath>)
const
329 for (
const auto & vit : curpath_)
330 if (vit == v)
return(
true);
336template <
class Vertex,
class Edge, GPathKind KIND>
337bool AllPathsVertices<Vertex,Edge,KIND>::isACycle
338 (
const typename GraphType::viterator & v,
339 GPathKindType<GPathKind::kEdgePath>)
const
342 typename GraphType::viterator vo,vd;
343 for (
const auto & eit : curpath_)
345 g_->connection(eit,vo,vd);
348 if (vo == v)
return(
true);
351 if (vd == v)
return(
true);
357template <
class Vertex,
class Edge, GPathKind KIND>
358void AllPathsVertices<Vertex,Edge,KIND>::doBacktrack(
void)
361 auto howmanyback = GraphType::ERange_DepthFirst::forceBacktrack(eit_);
374 curpath_.resize(curpath_.size()-howmanyback);
378template <
class Vertex,
class Edge, GPathKind KIND>
379void AllPathsVertices<Vertex,Edge,KIND>::nextEdge(
void)
384 if (eit == eend_) doBacktrack();
386 typename GraphType::viterator vo,vd;
387 g_->connection(eit_,vo,vd);
388 if (vd == vit1_)
return;
389 if ((detectcycles_)&&(isACycle(vd,GPathKindType<KIND>{}))) doBacktrack();
393template <
class Vertex,
class Edge, GPathKind KIND>
394void AllPathsVertices<Vertex,Edge,KIND>::constr_hidden(
395 const typename GraphType::viterator & v0,
396 GPathKindType<GPathKind::kVertexPath>)
400 curpath_.push_back(v0);
401 typename GraphType::viterator vo,vd;
404 g_->connection(eit_,vo,vd);
411 ELE_CODE_PAUSE({},
"");
414 curpath_.push_back(vd);
417 if ((detectcycles_)&&(isACycle(vd,GPathKindType<KIND>{})))
419 curpath_.push_back(vd);
425 curpath_.push_back(vd);
437template <
class Vertex,
class Edge, GPathKind KIND>
438bool AllPathsVertices<Vertex,Edge,KIND>::next_hidden(
439 GPathKindType<GPathKind::kVertexPath>)
442 if (isend_)
return(
false);
443 typename GraphType::viterator vo,vd;
444 g_->connection(eit_,vo,vd);
446 constr_hidden(vo,GPathKindType<GPathKind::kVertexPath>{});
451template <
class Vertex,
class Edge, GPathKind KIND>
452void AllPathsVertices<Vertex,Edge,KIND>::constr_hidden(
453 const typename GraphType::viterator & v0,
454 GPathKindType<GPathKind::kEdgePath>)
456 typename GraphType::viterator vo,vd;
459 g_->connection(eit_,vo,vd);
462 curpath_.push_back(eit_);
465 if ((detectcycles_)&&(isACycle(vd,GPathKindType<KIND>{})))
467 curpath_.push_back(eit_);
473 curpath_.push_back(eit_);
485template <
class Vertex,
class Edge, GPathKind KIND>
486bool AllPathsVertices<Vertex,Edge,KIND>::next_hidden(
487 GPathKindType<GPathKind::kEdgePath>)
490 if (isend_)
return(
false);
491 constr_hidden(vit0_,GPathKindType<GPathKind::kEdgePath>{});
502template <
class Vertex,
class Edge,
class Weight>
503void FloydWarshall<Vertex,Edge,Weight>::clean(
void)
506 ELE_CODE_TRACE({},
"Cleaning Floyd-Warshall");
507 if (ownposmap_)
delete posmap_;
508 if (distMatrix_ !=
nullptr)
delete [] distMatrix_;
509 if (nextMatrix_ !=
nullptr)
delete [] nextMatrix_;
512 distMatrix_ =
nullptr;
514 nextMatrix_ =
nullptr;
517template <
class Vertex,
class Edge,
class Weight>
518void FloydWarshall<Vertex,Edge,Weight>::
519 indexes(
const typename Gr::viterator vit0,
520 const typename Gr::viterator vit1,
525 i = posmap_->at(vit0);
526 if (vit0 == vit1) j = i;
527 else j = posmap_->at(vit1);
530template <
class Vertex,
class Edge,
class Weight>
537 distMatrix_{nullptr},
538 nextMatrix_{nullptr},
545 V2Size_ =
static_cast<size_t>(V_) *
static_cast<size_t>(V_);
546 ELE_CODE_TRACE({},
"Creating FLoyd-Warshall for " << g.
size_vertices() <<
547 " vertices and " << g.
size_edges() <<
" edges, V2Size_: "
550 distMatrix_ =
new double[V2Size_];
551 infs_ = std::vector<bool>(V2Size_,
true);
553 std::fill(nextMatrix_,nextMatrix_ + V2Size_, g.
vrangeAll().
end());
566 ELE_CODE_TRACE({},
"Initiating matrices with V = " << V_);
577 pos0 = posmap_->at(vit0);
578 pos1 = posmap_->at(vit1);
579 offs = offset(pos0,pos1);
581 distMatrix_[offs] = w(eit);
582 nextMatrix_[offs] = vit1;
589 pos0 = posmap_->at(vit);
590 offs = offset(pos0,pos0);
592 distMatrix_[offs] = 0.0;
593 nextMatrix_[offs] = vit;
597 ELE_CODE_TRACE({},
"Running search");
599 size_t offsij,offsik,offskj;
603 offsij = offset(i,j);
606 offsik = offset(i,k);
607 offskj = offset(k,j);
608 if ((!infs_[offsik]) && (!infs_[offskj]))
610 Weight sum{distMatrix_[offsik] + distMatrix_[offskj]};
611 if (infs_[offsij] || (distMatrix_[offsij] > sum))
613 infs_[offsij] =
false;
614 distMatrix_[offsij] = sum;
615 ELE_CODE_TRACE({},
"Changed dist(" << i <<
"," <<
616 j <<
") to " << sum);
617 nextMatrix_[offsij] = nextMatrix_[offsik];
623 if (std::find(infs_.begin(),infs_.end(),
true) != infs_.end())
624 ELE_CODE_TRACE({},
"Infs not wiped out");
632 ELE_CODE_TRACE({},
"Search finished ok. posmap_: " << posmap_);
635template <
class Vertex,
class Edge,
class Weight>
640 distMatrix_ = o.distMatrix_;
641 infs_ = std::move(o.infs_);
642 nextMatrix_ = o.nextMatrix_;
643 ownposmap_ = o.ownposmap_;
648 o.distMatrix_ =
nullptr;
649 o.nextMatrix_ =
nullptr;
651 o.ownposmap_ =
false;
654template <
class Vertex,
class Edge,
class Weight>
662 ELE_CODE_TRACE({},std::endl <<
"vit0: " << vit0.
to_string() << std::endl <<
663 "vit1: " << vit1.
to_string() << std::endl <<
664 "vit0 == vit1: " << (vit0==vit1) <<
668 indexes(vit0,vit1,i,j);
670 auto o = offset(i,j);
671 if (infs_[o])
return(
false);
676template <
class Vertex,
class Edge,
class Weight>
685 ELE_CODE_TRACE({},std::endl <<
"vit0: " << vit0.
to_string() << std::endl <<
686 "vit1: " << vit1.
to_string() << std::endl <<
687 "vit0 == vit1: " << (vit0==vit1) <<
691 indexes(vit0,vit1,i,j);
694 auto o = offset(i,j);
695 if (infs_[o])
return(
false);
702 indexes(vit,vit1,i,j);
703 vit = nextMatrix_[offset(i,j)];
eiterator begin(void) const
Must return an iterator pointing to the first element.
eiterator end(void) const
Must return an iterator pointing past the last element.
eiterator begin(void) const
Must return an iterator pointing to the first element.
eiterator end(void) const
Must return an iterator pointing past the last element.
A map (hash) from vertex iterators in a graph to their num. positions.
viterator end(void) const
Must return an iterator pointing past the last element.
viterator begin(void) const
Must return an iterator pointing to the first element.
#define ELE_CODE_TRACE_OFF
Place this inside local scope (e.g., routine) to deactivate traces there.
#define ELE_CODE_TRACE_ENDIF
Place this after a part of code that should be executed in debug only.
#define ELE_CODE_PLACE
Produces a std::string with the place of source where the macro is placed.
#define ELE_CODE_TRACE_IF
Place this before a part of code that should be executed in debug only.
Exception for indicating that some object is in invalid state.
#define ELE_CODE_INVSTATE(expl)
To throw an invalid-state exception with an explanation.
LongestUnsigned to_number(const void *p)
Convert a pointer address to a number.
A path in a graph whose vertices are of type Vertex and edges of type Edge.
std::function< Weight(const typename Graph< Vertex, Edge >::eiterator &) > EdgeWeightFunction
A family of functions that return the weight of an edge.
A type corresponding to each constant value of the kind of a path.
GPath< Vertex, Edge, KIND > PathType
Shortcut for the path type.
bool found(void) const noexcept
Return TRUE if there is some current path already found.
Graph< Vertex, Edge > GraphType
Shortcut for graph type.
const PathType & current(void) const
Return a reference to the last path found.
bool filled(void) const noexcept
Return TRUE if there is some previous calculation in the object.
~FloydWarshall(void)
Destructor.
bool next(void)
Search for another path and return TRUE if any is found.
const Gr::MapOfVItPos & mapOfVPoses(void) const
Return the vertex mapping used by the object.
A class that search for all paths connecting a given pair of vertices.
Floyd-Warshall data and algorithm to find all shortest paths in a graph.
AllPathsVertices(const GraphType &gr, const typename GraphType::viterator &vit0, const typename GraphType::viterator &vit1, bool detectcycles=true, const typename GraphType::EPred &epred=GraphType::trivial_epred)
Constructor for two given vertices.
FloydWarshall(const Gr &g, const EdgeWeightFunction< Vertex, Edge, Weight > &w=trivial_edge_weight< Vertex, Edge >, const typename Gr::MapOfVItPos *mpos=nullptr, const typename Gr::EPred &epred=Gr::trivial_epred)
Constructor: prepare data and perform the search.
bool shortest(const typename Gr::viterator vit0, const typename Gr::viterator vit1, Weight &d) const
Get the shortest distance (sum of weights) from vit0 to vit1.
virtual void connection(const eiterator &it, viterator &vorg, viterator &vdest) const
Fill VORG and VDEST with VRange_All iterators to the edge vertices.
std::function< bool(const Edge &) > EPred
Predicate that indicates which edges to iterate on.
virtual size_edge size_edges(void) const =0
Must return the number of edges.
ERange_DepthFirst erangeDepthFirst(const viterator &v) const
Return a range to iterate on edges in depth-first fashion.
virtual size_vertex size_vertices(void) const =0
Must return the number of vertices.
static constexpr bool trivial_epred(const Edge &) noexcept
A trivial predicate that always return true.
elementa::base::MultIterator< Edge > eiterator
Edge iterator. ForwardLegacyIterator.
elementa::base::MultIterator< Vertex > viterator
Vertex iterator. ForwardLegacyIterator.
VRange_All vrangeAll(void) const
Return a range to iterate on all Vertex data, no special order.
ERange_All erangeAll(void) const
Return a range to iterate on all Edge data, no special order.
All graph classes derive from this one.
size_t size_vertex
For holding numbers of vertices of a graph.
std::string to_string(void) const
Return a string with info about the iterator.
A mutable iterator that can have multiple iteration behaviors. Forward case.