3#include "elementa/license.inc"
4#include "elementa/checks.inc"
6#ifndef ELEMENTA_ADTS_GRAPHS_SPARSEGRAPHS_H
7#define ELEMENTA_ADTS_GRAPHS_SPARSEGRAPHS_H
72template <
class Vertex,
class Edge>
99 data_ = oth.data_; }
return(*
this); }
103 data_{std::move(oth.data_)}
109 data_ = std::move(oth.data_); }
return(*
this); }
127 {
return(data_.empty()); }
139 return(vallFromInternal(data_.origin(einternalFromMultit(it)))); }
144 return(vallFromInternal(data_.destination(einternalFromMultit(it))));}
153 {
return(vallFromInternal(data_.insert(v))); }
161 return(eallFromInternal(data_.connect(vinternalFromMultit(itv0),
162 vinternalFromMultit(itv1),e)));}
166 data_.unconnect(einternalFromMultit(ite)); }
168 void unconnect(
const typename BaseGraph::VectorOfEIts & sinds)
169 {
for (
const auto & ite:sinds) unconnect(ite); }
173 data_.erase(vinternalFromMultit(itv)); }
175 void erase(
const typename BaseGraph::VectorOfVIts & sinds)
176 {
for (
const auto & itv:sinds) erase(itv); }
185 { data_.splice(
dynamic_cast<SparseGraph &
>(oth).data_); }
196 using Cont = std::list<D>;
207 static size_t & getOffsetOfData(
void)
noexcept
208 {
static size_t ood{0};
return(ood); }
211 static const EInfo * startFromEdge(
const Edge * pd)
214 return(
reinterpret_cast<const EInfo *
>(
215 reinterpret_cast<const char *
>(pd) - getOffsetOfData()));
218 using List = Cont<EInfo>;
219 using ListOfIts = Cont<typename List::iterator>;
225 typename ListOfIts::iterator leaving;
226 typename ListOfIts::iterator entering;
228 typename List::iterator myselfit;
232 EInfo(
const Edge & d):data{d}
234 auto & ood = getOffsetOfData();
236 ood =
reinterpret_cast<char *
>(&data) -
237 reinterpret_cast<char *
>(
this);
240 EInfo(Edge && d):data{std::move(d)} {}
243 EInfo(
const EInfo & ) =
delete;
244 EInfo(EInfo && ) =
delete;
245 EInfo & operator=(
const EInfo & ) =
delete;
246 EInfo & operator=(EInfo && ) =
delete;
255 static size_t & getOffsetOfData(
void)
noexcept
256 {
static size_t ood{0};
return(ood); }
259 static const VInfo * startFromVertex(
const Vertex * pd)
262 return(
reinterpret_cast<const VInfo *
>(
263 reinterpret_cast<const char *
>(pd) - getOffsetOfData()));
266 using List = Cont<VInfo>;
267 using ListOfIts = Cont<typename List::iterator>;
271 typename EInfo::ListOfIts entering;
272 typename EInfo::ListOfIts leaving;
274 typename List::iterator myselfit;
278 VInfo(
const Vertex & d):data{d}
280 auto & ood = getOffsetOfData();
282 ood =
reinterpret_cast<char *
>(&data) -
283 reinterpret_cast<char *
>(
this);
286 VInfo(Vertex && d):data{std::move(d)} {}
289 VInfo(
const VInfo & ) =
delete;
290 VInfo(VInfo && ) =
delete;
291 VInfo & operator=(
const VInfo & ) =
delete;
292 VInfo & operator=(VInfo && ) =
delete;
305 typename VInfo::List vertices_;
306 typename EInfo::List edges_;
309 Data(
const Data & oth) { copyFrom(oth); }
310 Data(Data && oth) { moveFrom(std::move(oth)); }
312 Data & operator=(
const Data & oth)
313 {
if (
this != &oth) copyFrom(oth);
return(*
this); }
314 Data & operator=(Data && oth)
315 {
if (
this != &oth) moveFrom(std::move(oth));
return(*
this); }
319 bool empty(
void)
const noexcept
320 {
return( (vertices_.empty()) && (edges_.empty()) ); }
323 { vertices_.clear(); edges_.clear(); }
325 typename VInfo::List::size_type size_vertices(
void)
const
326 {
return(vertices_.size()); }
328 typename EInfo::List::size_type size_edges(
void)
const
329 {
return(edges_.size()); }
331 typename VInfo::List::iterator origin(
332 const typename EInfo::List::iterator & eit)
const
333 {
return((*eit).org->myselfit); }
335 typename VInfo::List::iterator destination(
336 const typename EInfo::List::iterator & eit)
const
337 {
return((*eit).dest->myselfit); }
339 typename VInfo::List::iterator insert(
const Vertex & v)
340 {
typename VInfo::List::iterator vit{
341 vertices_.emplace(vertices_.end(),v)};
342 fill(vit);
return(vit); }
344 typename VInfo::List::iterator insert(Vertex && v)
345 {
typename VInfo::List::iterator vit{
346 vertices_.emplace(vertices_.end(),std::move(v))};
347 fill(vit);
return(vit); }
349 typename EInfo::List::iterator connect(
350 const typename VInfo::List::iterator & itv0,
351 const typename VInfo::List::iterator & itv1,
353 {
typename EInfo::List::iterator eit{
354 edges_.emplace(edges_.end(),e)};
355 fill(eit,itv0,itv1);
return(eit); }
357 typename EInfo::List::iterator connect(
358 const typename VInfo::List::iterator & itv0,
359 const typename VInfo::List::iterator & itv1,
361 {
typename EInfo::List::iterator eit{
362 edges_.emplace(edges_.end(),std::move(e))};
363 fill(eit,itv0,itv1);
return(eit); }
365 void unconnect(
const typename EInfo::List::iterator & ite)
367 typename VInfo::List::iterator vit0{(*ite).org->myselfit};
368 typename VInfo::List::iterator vit1{(*ite).dest->myselfit};
369 (*vit0).leaving.erase((*ite).leaving);
370 (*vit1).entering.erase((*ite).entering);
374 void erase(
const typename VInfo::List::iterator & itv)
376 while (!(*itv).entering.empty())
377 unconnect(*((*itv).entering.begin()));
378 while (!(*itv).leaving.empty())
379 unconnect(*((*itv).leaving.begin()));
380 vertices_.erase(itv);
383 void splice(Data & oth)
384 { vertices_.splice(vertices_.end(),std::move(oth.vertices_));
385 edges_.splice(edges_.end(),std::move(oth.edges_)); }
389 void fill(
typename VInfo::List::iterator & vit)
390 { (*vit).myselfit = vit; }
392 void fill(
typename EInfo::List::iterator & eit,
393 const typename VInfo::List::iterator & itv0,
394 const typename VInfo::List::iterator & itv1)
396 (*eit).myselfit = eit;
397 (*eit).org = &(*itv0);
398 (*eit).dest = &(*itv1);
399 auto itinv0 = (*itv0).leaving.insert((*itv0).leaving.end(),eit);
400 auto itinv1 = (*itv1).entering.insert((*itv1).entering.end(),eit);
401 (*eit).leaving = itinv0;
402 (*eit).entering = itinv1;
405 void moveFrom(Data && oth)
410 vertices_ = std::move(oth.vertices_);
411 edges_ = std::move(oth.edges_);
414 void copyFrom(
const Data & oth)
417 std::map<const VInfo *, const VInfo *> vmap;
418 for (
const auto & v: oth.vertices_) vmap[&v] = &(*insert(v.data));
419 for (
const auto & e: oth.edges_)
420 connect(vmap.at(e.org)->myselfit,
421 vmap.at(e.dest)->myselfit,
439 VItImpl_All(
const typename VInfo::List & vdata,
440 const typename VInfo::List::iterator & vi):
445 VItImpl_All(
const VItImpl_All & oth):
446 elementa::patterns::Validatable{oth},
449 ELE_CODE_TRACE({},
"oth.valid: " <<
450 oth.elementa::patterns::Validatable::valid());
452 ELE_CODE_TRACE({},
"valid: " <<
455 VItImpl_All &
operator=(
const VItImpl_All &oth)
457 ELE_CODE_TRACE({},
"oth.valid: " <<
458 oth.elementa::patterns::Validatable::valid());
463 ELE_CODE_TRACE({},
"valid: " <<
467 VItImpl_All(VItImpl_All && oth):
468 elementa::patterns::Validatable{std::move(oth)},
469 elementa::base::
MultItImpl<Vertex>{std::move(oth)}
471 ELE_CODE_TRACE({},
"oth.valid: " <<
472 oth.elementa::patterns::Validatable::valid());
474 ELE_CODE_TRACE({},
"valid: " <<
477 VItImpl_All &
operator=(VItImpl_All && oth)
479 ELE_CODE_TRACE({},
"oth.valid: " <<
480 oth.elementa::patterns::Validatable::valid());
485 ELE_CODE_TRACE({},
"valid: " <<
489 typename BaseGraph::viterator::ImplementationPtr clone(
void)
const
491 ELE_CODE_TRACE({},
"valid: " <<
493 return(
typename BaseGraph::viterator::ImplementationPtr{
494 new VItImpl_All{*
this}}); }
496 Vertex & operator*(
void)
499 Vertex * pointedData(
void)
const
500 {
if (pos_ == vdata_->end())
return(
nullptr);
501 return(&((*pos_).data)); }
503 VItImpl_All & operator++(
void)
504 {
if (pos_ != vdata_->end()) ++pos_;
return(*
this); }
506 std::string to_string(
void)
const override
507 {
return(std::string{
"vit_all(vdata:"} +
512 void checkDeref(
const std::string & place =
"")
const
513 {
if (pos_ == vdata_->end())
515 "De-referencing end iterator"}.asEXC(
520 const typename VInfo::List * vdata_;
521 typename VInfo::List::iterator pos_;
523 void copyFrom(
const VItImpl_All & oth)
524 { vdata_ = oth.vdata_; pos_ = oth.pos_; }
534 EItImpl_All(
const typename EInfo::List & edata,
535 const typename EInfo::List::iterator & ei):
540 EItImpl_All(
const EItImpl_All & oth):
541 elementa::patterns::Validatable{oth},
545 EItImpl_All &
operator=(
const EItImpl_All &oth)
549 copyFrom(oth); }
return(*
this); }
551 EItImpl_All(EItImpl_All && oth):
552 elementa::patterns::Validatable{std::move(oth)},
553 elementa::base::
MultItImpl<Edge>{std::move(oth)}
556 EItImpl_All &
operator=(EItImpl_All && oth)
560 copyFrom(oth); }
return(*
this); }
562 typename BaseGraph::eiterator::ImplementationPtr clone(
void)
const
563 {
return(
typename BaseGraph::eiterator::ImplementationPtr{
564 new EItImpl_All{*
this}}); }
566 Edge & operator*(
void)
569 Edge * pointedData(
void)
const
570 {
if (pos_ == edata_->end())
return(
nullptr);
571 return(&((*pos_).data)); }
573 EItImpl_All & operator++(
void)
574 {
if (pos_ != edata_->end()) ++pos_;
return(*
this); }
576 std::string to_string(
void)
const override
577 {
return(std::string{
"eit_all(vdata:"} +
582 void checkDeref(
const std::string & place =
"")
const
583 {
if (pos_ == edata_->end())
585 "De-referencing end iterator"}.asEXC(
590 const typename EInfo::List * edata_;
591 typename EInfo::List::iterator pos_;
593 void copyFrom(
const EItImpl_All & oth)
594 { edata_ = oth.edata_; pos_ = oth.pos_; }
604 EItImpl_Leaving(
const typename VInfo::List & vdata,
605 const typename VInfo::List::iterator & vi,
606 bool beginorend =
true)
608 if (vi != vdata.end())
610 cdata_ = &((*vi).leaving);
611 if (beginorend) pos_ = cdata_->begin();
612 else pos_ = cdata_->end();
617 EItImpl_Leaving(
const EItImpl_Leaving & oth):
618 elementa::patterns::Validatable{oth},
622 EItImpl_Leaving &
operator=(
const EItImpl_Leaving &oth)
626 copyFrom(oth); }
return(*
this); }
628 EItImpl_Leaving(EItImpl_Leaving && oth):
629 elementa::patterns::Validatable{std::move(oth)},
630 elementa::base::
MultItImpl<Edge>{std::move(oth)}
633 EItImpl_Leaving &
operator=(EItImpl_Leaving && oth)
637 copyFrom(oth); }
return(*
this); }
639 typename BaseGraph::eiterator::ImplementationPtr clone(
void)
const
640 {
return(
typename BaseGraph::eiterator::ImplementationPtr{
641 new EItImpl_Leaving{*
this}}); }
643 Edge & operator*(
void)
646 Edge * pointedData(
void)
const
648 if (pos_ == cdata_->end())
return(
nullptr);
649 return(&((*(*pos_)).data)); }
651 EItImpl_Leaving & operator++(
void)
653 if (pos_ != cdata_->end()) ++pos_;
656 std::string to_string(
void)
const override
657 {
return(std::string{
"eit_leaving(cdata:"} +
662 void checkDeref(
const std::string & place =
"")
const
665 if (pos_ == cdata_->end())
667 "De-referencing end iterator"}.asEXC(
672 typename EInfo::ListOfIts * cdata_;
673 typename EInfo::ListOfIts::iterator pos_;
675 void copyFrom(
const EItImpl_Leaving & oth)
676 { cdata_ = oth.cdata_; pos_ = oth.pos_; }
685 EItImpl_Entering(
const typename VInfo::List & vdata,
686 const typename VInfo::List::iterator & vi,
687 bool beginorend =
true)
689 if (vi != vdata.end())
691 cdata_ = &((*vi).entering);
692 if (beginorend) pos_ = cdata_->begin();
693 else pos_ = cdata_->end();
698 EItImpl_Entering(
const EItImpl_Entering & oth):
699 elementa::patterns::Validatable{oth},
703 EItImpl_Entering &
operator=(
const EItImpl_Entering &oth)
707 copyFrom(oth); }
return(*
this); }
709 EItImpl_Entering(EItImpl_Entering && oth):
710 elementa::patterns::Validatable{std::move(oth)},
711 elementa::base::
MultItImpl<Edge>{std::move(oth)}
714 EItImpl_Entering &
operator=(EItImpl_Entering && oth)
718 copyFrom(oth); }
return(*
this); }
720 typename BaseGraph::eiterator::ImplementationPtr clone(
void)
const
721 {
return(
typename BaseGraph::eiterator::ImplementationPtr{
722 new EItImpl_Entering{*
this}}); }
724 Edge & operator*(
void)
727 Edge * pointedData(
void)
const
730 if (pos_ == cdata_->end())
return(
nullptr);
731 return(&((*(*pos_)).data));
734 EItImpl_Entering & operator++(
void)
737 if (pos_ != cdata_->end()) ++pos_;
741 std::string to_string(
void)
const override
742 {
return(std::string{
"eit_entering(cdata:"} +
747 void checkDeref(
const std::string & place =
"")
const
751 if (pos_ == cdata_->end())
753 "De-referencing end iterator"}.asEXC(
759 typename EInfo::ListOfIts * cdata_;
760 typename EInfo::ListOfIts::iterator pos_;
762 void copyFrom(
const EItImpl_Entering & oth)
763 { cdata_ = oth.cdata_; pos_ = oth.pos_; }
770 const std::string & place =
"")
const
772 if ((!v.valid()) || (v.isEnd()))
774 std::string{(v.valid() ?(v.isEnd() ?
"End" :
"") :
775 (v.isEnd() ?
"Invalid+End" :
"Invalid"))} +
776 " vertex iterator"}.asEXC(place.empty() ?
781 const std::string & place =
"")
const
783 if ((!e.valid()) || (e.isEnd()))
785 std::string{(e.valid() ?(e.isEnd() ?
"End" :
"") :
786 (e.isEnd() ?
"Invalid+End" :
"Invalid"))} +
787 " edge iterator"}.asEXC(place.empty() ?
795 const typename VInfo::List::iterator & vi)
const
797 typename BaseGraph::viterator::ImplementationPtr{
798 new VItImpl_All{data_.vertices_,vi}}}); }
801 const typename EInfo::List::iterator & ei)
const
803 typename BaseGraph::eiterator::ImplementationPtr{
804 new EItImpl_All{data_.edges_,ei}}}); }
806 typename VInfo::List::iterator vinternalFromMultit(
809 return(VInfo::startFromVertex(&(*vit))->myselfit); }
811 typename EInfo::List::iterator einternalFromMultit(
814 return(EInfo::startFromEdge(&(*eit))->myselfit); }
820 {
return(vallFromInternal(
821 const_cast<typename VInfo::List &
>(data_.vertices_).begin())); }
824 {
return(vallFromInternal(
825 const_cast<typename VInfo::List &
>(data_.vertices_).end())); }
828 {
return(eallFromInternal(
829 const_cast<typename EInfo::List &
>(data_.edges_).begin())); }
832 {
return(eallFromInternal(
833 const_cast<typename EInfo::List &
>(data_.edges_).end())); }
839 typename BaseGraph::eiterator::ImplementationPtr{
840 new EItImpl_Leaving{data_.vertices_,
841 vinternalFromMultit(v)}}}); }
847 typename BaseGraph::eiterator::ImplementationPtr{
848 new EItImpl_Leaving{data_.vertices_,
849 vinternalFromMultit(v),
false}}}); }
855 typename BaseGraph::eiterator::ImplementationPtr{
856 new EItImpl_Entering{data_.vertices_,
857 vinternalFromMultit(v)}}}); }
863 typename BaseGraph::eiterator::ImplementationPtr{
864 new EItImpl_Entering{data_.vertices_,
865 vinternalFromMultit(v),
false}}}); }
A vector of edge iterators (might be repeated).
A vector of vertex iterators (might be repeated).
#define ELE_CODE_TRACE_OFF
Place this inside local scope (e.g., routine) to deactivate traces there.
#define ELE_CODE_PLACE
Produces a std::string with the place of source where the macro is placed.
Exception for indicating that some argument of a method/function is invalid.
Exception for indicating that some object is in invalid state.
LongestUnsigned to_number(const void *p)
Convert a pointer address to a number.
elementa::base::MultIterator< Edge > eiterator
Edge iterator. ForwardLegacyIterator.
elementa::base::MultIterator< Vertex > viterator
Vertex iterator. ForwardLegacyIterator.
Graph & operator=(const Graph &oth)=default
Copy assignment.
All graph classes derive from this one.
size_t size_vertex
For holding numbers of vertices of a graph.
size_t size_edge
For holding numbers of edges of a graph.
MultItImpl & operator=(const MultItImpl &oth)
Copy assignment.
MultItImpl(void)
Default constructor: invalid state.
Base class for implementing diverse iteration behaviors.
A mutable iterator that can have multiple iteration behaviors. Forward case.
size_vertex size_vertices(void) const
Must return the number of vertices.
SparseGraph & operator=(const SparseGraph &oth)
Copy assignment.
SparseGraph(SparseGraph &&oth)
Move constructor.
SparseGraph(void)
Default constructor.
SparseGraph * emptyClone(void) const override
Derived classes can override this to provide a clone that is "empty".
void splice(BaseGraph &oth, typename BaseGraph::VectorOfVIts *svothinds=nullptr, typename BaseGraph::VectorOfEIts *seothinds=nullptr, typename BaseGraph::VectorOfVIts *svinds=nullptr, typename BaseGraph::VectorOfEIts *seinds=nullptr)
size_edge size_edges(void) const
Must return the number of edges.
BaseGraph::viterator insert(const Vertex &v)
Must insert one more vertex in the graph, unconnected to any other.
SparseGraph(const SparseGraph &oth)
Copy constructor.
bool empty(void) const
Must return true if the graph is empty.
virtual ~SparseGraph(void)
Destructor.
SparseGraph & operator=(SparseGraph &&oth)
Move assignment.
SparseGraph * clone(void) const
Derived classes must implement this method varying its return type.
void clear(void)
Must clear the content of the graph.
A graph that stores all its info in a sparse manner.
Validatable & operator=(const Validatable &oth)
Derived classes must call this base optor if they have non-default ones.
bool valid(void) const noexcept
Public method to be used by users of the derived class.
virtual void checkValid(const std::string &place="") const
Call this method if an exception is needed when in invalid state.
void setValid(bool defval=true) noexcept
Derived classes can rewrite their own (hiding this, calling this).