The Original CHomP Software
digraph.h
Go to the documentation of this file.
1
3
15
16// Copyright (C) 1997-2021 by Pawel Pilarczyk.
17//
18// This file is part of my research software package. This is free software:
19// you can redistribute it and/or modify it under the terms of the GNU
20// General Public License as published by the Free Software Foundation,
21// either version 3 of the License, or (at your option) any later version.
22//
23// This software is distributed in the hope that it will be useful,
24// but WITHOUT ANY WARRANTY; without even the implied warranty of
25// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26// GNU General Public License for more details.
27//
28// You should have received a copy of the GNU General Public License
29// along with this software; see the file "license.txt". If not,
30// please, see <https://www.gnu.org/licenses/>.
31
32// Started in January 2006. Last revision: August 2, 2021.
33
34
35#ifndef _CHOMP_STRUCT_DIGRAPH_H_
36#define _CHOMP_STRUCT_DIGRAPH_H_
37
38#include <iostream>
39#include <new>
40#include <stack>
41#include <queue>
42#include <set>
43#include <memory>
44#include <vector>
45#include <algorithm>
46
56
57namespace chomp {
58namespace homology {
59
60
61// --------------------------------------------------
62// ----------------- DUMMY ROUNDING -----------------
63// --------------------------------------------------
64
67template <class numType>
69{
70public:
72 static inline numType add_down (const numType &x, const numType &y)
73 { return x + y; }
74
76 static inline numType add_up (const numType &x, const numType &y)
77 { return x + y; }
78
80 static inline numType sub_down (const numType &x, const numType &y)
81 { return x - y; }
82
84 static inline numType sub_up (const numType &x, const numType &y)
85 { return x - y; }
86
88 static inline numType mul_down (const numType &x, const numType &y)
89 { return x * y; }
90
92 static inline numType mul_up (const numType &x, const numType &y)
93 { return x * y; }
94
96 static inline numType div_down (const numType &x, const numType &y)
97 { return x / y; }
98
100 static inline numType div_down (const numType &x, int_t y)
101 { return x / y; }
102
104 static inline numType div_up (const numType &x, const numType &y)
105 { return x / y; }
106
107private:
108}; /* class dummyRounding */
109
110
111// --------------------------------------------------
112// ------------------ DUMMY ARRAY -------------------
113// --------------------------------------------------
114
117{
118public:
120 dummyArray () {n = 0;}
121
124
125private:
128
129}; /* class dummyArray */
130
131
132// --------------------------------------------------
133// ----------------- DIRECTED GRAPH -----------------
134// --------------------------------------------------
135
136// #define DIGRAPH_DEBUG
137
141template <class wType = int>
143{
144public:
146 typedef wType weight_type;
147
151 diGraph ();
152
154 ~diGraph ();
155
157 void swap (diGraph<wType> &g);
158
160 void addVertex (void);
161
164 void addEdge (int_t target);
165
168 void addEdge (int_t target, const wType &weight);
169
171 void setWeight (int_t vertex, int_t i, const wType &weight);
172
174 void setWeight (int_t edge, const wType &weight);
175
178 template <class Table>
179 void setWeights (const Table &tab);
180
183 void removeVertex (void);
184
189 void removeVertex (int_t vertex, bool updateweights = false);
190
192 int_t countVertices (void) const;
193
195 int_t countEdges (void) const;
196
198 int_t countEdges (int_t vertex) const;
199
201 int_t getEdge (int_t vertex, int_t i) const;
202
204 const wType &getWeight (int_t vertex, int_t i) const;
205
207 const wType &getWeight (int_t edge) const;
208
211 template <class Table>
212 void getWeights (Table &tab) const;
213
217 template <class Table>
218 void writeEdges (Table &tab) const;
219
221 template <class wType1>
222 void transpose (diGraph<wType1> &result,
223 bool copyweights = false) const;
224
228 template <class Table, class wType1>
229 void subgraph (diGraph<wType1> &result, const Table &tab,
230 bool copyweights = false) const;
231
235 template <class Table, class Color>
236 void DFScolor (Table &tab, const Color &color,
237 int_t vertex = 0) const;
238
240 template <class Table, class Color>
241 void DFScolorRecurrent (Table &tab, const Color &color,
242 int_t vertex = 0) const;
243
245 template <class Table, class Color>
246 void DFScolorStack (Table &tab, const Color &color,
247 int_t vertex = 0) const;
248
251 template <class Table>
252 void DFSfinishTime (Table &tab) const;
253
263 template <class Table1, class Table2, class Table3>
264 int_t DFSforest (const Table1 &ordered, Table2 &compVertices,
265 Table3 &compEnds, bool nontrivial = false,
266 diGraph<wType> *sccGraph = 0) const;
267
273 int_t shortestPath (int_t source, int_t destination) const;
274
279 int_t shortestLoop (int_t origin) const;
280
288 template <class lenTable, class weightsType, class roundType>
289 void Dijkstra (const roundType &rounding, int_t source,
290 lenTable &len, weightsType &edgeWeights) const;
291
293 template <class lenTable, class roundType>
294 void Dijkstra (const roundType &rounding, int_t source,
295 lenTable &len) const;
296
298 template <class lenTable>
299 void Dijkstra (int_t source, lenTable &len) const;
300
311 template <class lenTable, class predTable, class roundType>
312 bool BellmanFord (const roundType &rounding, int_t source,
313 lenTable &len, wType *infinity, predTable pred) const;
314
316 template <class lenTable, class predTable>
317 bool BellmanFord (int_t source, lenTable &len, wType *infinity,
318 predTable pred) const;
319
323 template <class roundType>
324 bool BellmanFord (const roundType &rounding, int_t source) const;
325
327 bool BellmanFord (int_t source) const;
328
335 wType Edmonds () const;
336
338 wType EdmondsOld () const;
339
354 template <class arrayType, class roundType>
355 wType FloydWarshall (const roundType &rounding, arrayType &arr,
356 bool setInfinity = true, bool ignoreNegLoop = false) const;
357
359 template <class arrayType>
360 wType FloydWarshall (arrayType &arr, bool setInfinity = true,
361 bool ignoreNegLoop = false) const;
362
371 template <class arrayType, class roundType>
372 wType Johnson (const roundType &rounding, arrayType &arr,
373 bool setInfinity = true, bool ignoreNegLoop = false) const;
374
376 template <class arrayType>
377 wType Johnson (arrayType &arr, bool setInfinity = true,
378 bool ignoreNegLoop = false) const;
379
389 template <class roundType>
390 wType minPathWeight (const roundType &rounding,
391 bool ignoreNegLoop = false, int sparseGraph = -1) const;
392
394 wType minPathWeight (bool ignoreNegLoop = false,
395 int sparseGraph = -1) const;
396
401 wType minMeanCycleWeight (diGraph<wType> *transposed = 0) const;
402
411 template <class roundType>
412 wType minMeanCycleWeight (const roundType &rounding,
413 diGraph<wType> *transposed) const;
414
422 template <class roundType, class predType>
423 wType minMeanCycleWeightMem (const roundType &rounding,
424 diGraph<wType> *transposed, predType &predecessors) const;
425
427 template <class roundType>
428 wType minMeanCycleWeightMem (const roundType &rounding,
429 diGraph<wType> *transposed) const;
430
436 template <class arrayType, class roundType>
437 wType minMeanPathWeight (const roundType &rounding,
438 const arrayType &starting, int_t n) const;
439
441 template <class arrayType>
442 wType minMeanPathWeight (const arrayType &starting, int_t n) const;
443
446 template <class wType1, class wType2>
447 friend bool operator == (const diGraph<wType1> &g1,
448 const diGraph<wType2> &g2);
449
451 template <class outType>
452 outType &show (outType &out, bool showWeights = false) const;
453
454protected:
457
461
464
467
468private:
470 template <class Table>
471 void DFSfinishTimeRecurrent (Table &tab, int_t vertex,
472 int_t &counter) const;
473
475 template <class Table>
476 void DFSfinishTimeStack (Table &tab, int_t vertex,
477 int_t &counter) const;
478
481 template <class Table1, class Table2>
482 bool DFSforestRecurrent (Table1 &tab, Table1 &ntab, int_t vertex,
483 int_t treeNumber, int_t countTrees, Table2 &compVertices,
484 int_t &curVertex, diGraph *sccGraph, int_t *sccEdgeAdded)
485 const;
486
488 template <class Table1, class Table2>
489 bool DFSforestStack (Table1 &tab, Table1 &ntab, int_t vertex,
490 int_t treeNumber, int_t countTrees, Table2 &compVertices,
491 int_t &curVertex, diGraph *sccGraph, int_t *sccEdgeAdded)
492 const;
493
496 {
500
502 wType weight;
503
505 friend bool operator < (const edgeTriple &x,
506 const edgeTriple &y)
507 {
508 return (x. weight < y. weight);
509 }
510 };
511
515 {
516 public:
519 {
520 value = 0;
521 return;
522 }
523
525 explicit posWeight (const wType &_value)
526 {
527 if (_value < 0)
528 value = 0;
529 else
530 value = _value;
531 return;
532 }
533
536 {
537 value = -1;
538 return;
539 }
540
542 bool isInfinity () const
543 {
544 return (value < 0);
545 }
546
548 const wType &getValue () const
549 {
550 return value;
551 }
552
554 friend bool operator < (const posWeight &x,
555 const posWeight &y)
556 {
557 if (y. isInfinity ())
558 return !(x. isInfinity ());
559 else if (x. isInfinity ())
560 return false;
561 return (x. value < y. value);
562 }
563
565 friend std::ostream &operator << (std::ostream &out,
566 const posWeight &x)
567 {
568 if (x. isInfinity ())
569 out << "+oo";
570 else
571 out << x. getValue ();
572 return out;
573 }
574
575 private:
577 wType value;
578 };
579
580}; /* class diGraph */
581
582// --------------------------------------------------
583
584template <class wType>
585inline diGraph<wType>::diGraph (): nVertices (0),
586 edgeEnds (1024), edges (4096), weights (4096)
587{
588 return;
589} /* diGraph::diGraph */
590
591template <class wType>
593{
594 return;
595} /* diGraph::~diGraph */
596
597// --------------------------------------------------
598
599template <class wType1, class wType2>
600inline bool operator == (const diGraph<wType1> &g1,
601 const diGraph<wType2> &g2)
602{
603 if (g1. nVertices != g2. nVertices)
604 return false;
605 if (!g1. nVertices)
606 return true;
607 for (int_t i = 0; i < g1. nVertices; ++ i)
608 {
609 if (g1. edgeEnds [i] != g2. edgeEnds [i])
610 return false;
611 }
612 int_t nEdges = g1. edgeEnds [g1. nVertices - 1];
613 for (int_t i = 0; i < nEdges; ++ i)
614 {
615 if (g1. edges [i] != g2. edges [i])
616 return false;
617 }
618 return true;
619} /* operator == */
620
621template <class wType1, class wType2>
622inline bool operator != (const diGraph<wType1> &g1,
623 const diGraph<wType2> &g2)
624{
625 return !(g1 == g2);
626} /* operator != */
627
628// --------------------------------------------------
629
630template <class wType>
632{
633 std::swap (nVertices, g. nVertices);
634 edgeEnds. swap (g. edgeEnds);
635 edges. swap (g. edges);
636 weights. swap (g. weights);
637 return;
638} /* diGraph::swap */
639
640template <class wType>
642{
643 edgeEnds [nVertices] = nVertices ? edgeEnds [nVertices - 1] :
644 static_cast<int_t> (0);
645 ++ nVertices;
646 return;
647} /* diGraph::addVertex */
648
649template <class wType>
650inline void diGraph<wType>::addEdge (int_t target)
651{
652 if (!nVertices)
653 throw "Trying to add an edge to an empty graph.";
654// if (target >= nVertices)
655// throw "Trying to add an edge to a nonexistent vertex.";
656 if (target < 0)
657 throw "Trying to add an edge to a negative vertex.";
658 int_t &offset = edgeEnds [nVertices - 1];
659 if (offset + 1 <= 0)
660 throw "Too many edges in a diGraph (limit = 2,147,483,647).";
661 edges [offset] = target;
662 ++ offset;
663 return;
664} /* diGraph::addEdge */
665
666template <class wType>
667inline void diGraph<wType>::addEdge (int_t target, const wType &weight)
668{
669 if (!nVertices)
670 throw "Trying to add an edge to an empty graph.";
671// if (target >= nVertices)
672// throw "Trying to add an edge to a nonexistent vertex.";
673 if (target < 0)
674 throw "Trying to add an edge to a negative vertex.";
675 int_t &offset = edgeEnds [nVertices - 1];
676 if (offset + 1 <= 0)
677 throw "Too many edges in a diGraph (limit = 2,147,483,647).";
678 edges [offset] = target;
679 weights [offset] = weight;
680 ++ offset;
681 return;
682} /* diGraph::addEdge */
683
684template <class wType>
685inline void diGraph<wType>::setWeight (int_t vertex, int_t i,
686 const wType &weight)
687{
688 if (!vertex)
689 weights [i] = weight;
690 else
691 weights [edgeEnds [vertex - 1] + i] = weight;
692 return;
693} /* diGraph::setWeight */
694
695template <class wType>
696inline void diGraph<wType>::setWeight (int_t edge, const wType &weight)
697{
698 weights [edge] = weight;
699 return;
700} /* diGraph::setWeight */
701
702template <class wType> template <class Table>
703inline void diGraph<wType>::setWeights (const Table &tab)
704{
705 if (!nVertices)
706 return;
707 int_t nEdges = edgeEnds [nVertices - 1];
708 for (int_t i = 0; i < nEdges; ++ i)
709 weights [i] = tab [i];
710 return;
711} /* diGraph::setWeights */
712
713template <class wType>
715{
716 if (!nVertices)
717 throw "Trying to remove a vertex from the empty graph.";
718 -- nVertices;
719 return;
720} /* diGraph::removeVertex */
721
722template <class wType>
723inline void diGraph<wType>::removeVertex (int_t vertex, bool updateweights)
724{
725 // make sure that the vertex number is within the scope
726 if ((vertex < 0) || (vertex >= nVertices))
727 throw "Trying to remove a vertex that is not in the graph.";
728
729 // remove edges that begin or end at the given vertex
730 int_t curEdge = 0;
731 int_t newEdge = 0;
732 int_t skipped = 0;
733 for (int_t v = 0; v < nVertices; ++ v)
734 {
735 // skip the edges that begin at the given vertex
736 if (!skipped && (v == vertex))
737 {
738 curEdge = edgeEnds [v];
739 ++ skipped;
740 continue;
741 }
742
743 // skip the edges that point to the given vertex
744 int_t maxEdge = edgeEnds [v];
745 for (; curEdge < maxEdge; ++ curEdge)
746 {
747 if (edges [curEdge] == vertex)
748 continue;
749 int_t target = edges [curEdge];
750 edges [newEdge] = (target < vertex) ? target :
751 (target - 1);
752 if (updateweights)
753 weights [newEdge] = weights [curEdge];
754 ++ newEdge;
755 }
756 edgeEnds [v - skipped] = newEdge;
757 }
758
759 // decrease the number of vertices
760 nVertices -= skipped;
761
762 return;
763} /* diGraph::removeVertex */
764
765template <class wType>
767{
768 return nVertices;
769} /* diGraph::countVertices */
770
771template <class wType>
773{
774 if (!nVertices)
775 return 0;
776 else
777 return edgeEnds [nVertices - 1];
778} /* diGraph::countEdges */
779
780template <class wType>
782{
783 if (!vertex)
784 return edgeEnds [0];
785 else
786 return edgeEnds [vertex] - edgeEnds [vertex - 1];
787} /* diGraph::countEdges */
788
789template <class wType>
790inline int_t diGraph<wType>::getEdge (int_t vertex, int_t i) const
791{
792 if (!vertex)
793 return edges [i];
794 else
795 return edges [edgeEnds [vertex - 1] + i];
796} /* diGraph::getEdge */
797
798template <class wType>
799inline const wType &diGraph<wType>::getWeight (int_t vertex, int_t i) const
800{
801 if (!vertex)
802 return weights [i];
803 else
804 return weights [edgeEnds [vertex - 1] + i];
805} /* diGraph::getWeight */
806
807template <class wType>
808inline const wType &diGraph<wType>::getWeight (int_t edge) const
809{
810 return weights [edge];
811} /* diGraph::getWeight */
812
813template <class wType> template <class Table>
814inline void diGraph<wType>::getWeights (Table &tab) const
815{
816 if (!nVertices)
817 return;
818 int_t nEdges = edgeEnds [nVertices - 1];
819 for (int_t i = 0; i < nEdges; ++ i)
820 tab [i] = weights [i];
821 return;
822} /* diGraph::getWeights */
823
824template <class wType> template <class Table>
825inline void diGraph<wType>::writeEdges (Table &tab) const
826{
827 int_t curEdge = 0;
828 for (int_t curVertex = 0; curVertex < nVertices; ++ curVertex)
829 {
830 int_t maxEdge = edgeEnds [curVertex];
831 while (curEdge < maxEdge)
832 {
833 tab [curEdge] [0] = curVertex;
834 tab [curEdge] [1] = edges [curEdge];
835 ++ curEdge;
836 }
837 }
838 return;
839} /* diGraph::writeEdges */
840
841template <class wType> template <class wType1>
843 bool copyweights) const
844{
845 // prepare the resulting graph
846 result. nVertices = nVertices;
847 if (!nVertices)
848 return;
849
850 // compute the initial offsets for the edge numbers
851 for (int_t i = 0; i < nVertices; ++ i)
852 result. edgeEnds [i] = 0;
853 int_t nEdges = edgeEnds [nVertices - 1];
854 for (int_t i = 0; i < nEdges; ++ i)
855 {
856 if (edges [i] < nVertices - 1)
857 ++ result. edgeEnds [edges [i] + 1];
858 }
859 for (int_t i = 2; i < nVertices; ++ i)
860 result. edgeEnds [i] += result. edgeEnds [i - 1];
861
862 // compute the reversed edges
863 int_t curEdge = 0;
864 for (int_t i = 0; i < nVertices; ++ i)
865 {
866 for (; curEdge < edgeEnds [i]; ++ curEdge)
867 {
868 int_t j = edges [curEdge];
869 int_t &offset = result. edgeEnds [j];
870 result. edges [offset] = i;
871 if (copyweights)
872 result. weights [offset] = weights [curEdge];
873 ++ offset;
874 }
875 }
876 return;
877} /* diGraph::transpose */
878
879template <class wType> template <class Table, class wType1>
881 const Table &tab, bool copyweights) const
882{
883 // compute the new numbers of vertices that remain in the graph
884 int_t *numbers = new int_t [nVertices];
885 int_t curNumber = 0;
886 for (int_t i = 0; i < nVertices; ++ i)
887 {
888 if (tab [i])
889 numbers [i] = curNumber ++;
890 else
891 numbers [i] = -1;
892 }
893
894 // copy the edges from the old graph to the new one
895 for (int_t i = 0; i < nVertices; ++ i)
896 {
897 if (numbers [i] < 0)
898 continue;
899 g. addVertex ();
900 int_t firstEdge = i ? edgeEnds [i - 1] :
901 static_cast<int_t> (0);
902 int_t endEdge = edgeEnds [i];
903 for (int_t j = firstEdge; j < endEdge; ++ j)
904 {
905 int_t edgeEnd = edges [j];
906 if (numbers [edgeEnd] >= 0)
907 {
908 if (copyweights)
909 g. addEdge (numbers [edgeEnd],
910 weights [j]);
911 else
912 g. addEdge (numbers [edgeEnd]);
913 }
914 }
915 }
916
917 // clean up memory and exit
918 delete [] numbers;
919 return;
920} /* diGraph::subgraph */
921
922// --------------------------------------------------
923
924template <class wType> template <class Table, class Color>
925inline void diGraph<wType>::DFScolorRecurrent (Table &tab,
926 const Color &color, int_t vertex) const
927{
928 tab [vertex] = color;
929 int_t maxEdge = edgeEnds [vertex];
930 for (int_t i = vertex ? edgeEnds [vertex - 1] :
931 static_cast<int_t> (0); i < maxEdge; ++ i)
932 {
933 int_t next = edges [i];
934 if (tab [next] != color)
935 DFScolorRecurrent (tab, color, next);
936 }
937 return;
938} /* diGraph::DFScolorRecurrent */
939
940template <class wType> template <class Table, class Color>
941inline void diGraph<wType>::DFScolorStack (Table &tab, const Color &color,
942 int_t vertex) const
943{
944 // prepare stacks for the recursion
945 std::stack<int_t> s_vertex;
946 std::stack<int_t> s_edge;
947 std::stack<int_t> s_maxedge;
948
949 // mark the current vertex as visited
950 tab [vertex] = color;
951
952 // determine the edges to be visited
953 int_t edge = vertex ? edgeEnds [vertex - 1] :
954 static_cast<int_t> (0);
955 int_t maxedge = edgeEnds [vertex];
956
957 while (1)
958 {
959 // return to the previous recursion level
960 // if all the edges have been followed
961 if (edge >= maxedge)
962 {
963 // return if this is the initial recursion level
964 if (s_vertex. empty ())
965 return;
966
967 // restore the variables from the previous level
968 vertex = s_vertex. top ();
969 s_vertex. pop ();
970 edge = s_edge. top ();
971 s_edge. pop ();
972 maxedge = s_maxedge. top ();
973 s_maxedge. pop ();
974 continue;
975 }
976
977 // go to the deeper recursion level if possible
978 int_t next = edges [edge ++];
979 if (tab [next] != color)
980 {
981 // store the previous variables at the stacks
982 s_vertex. push (vertex);
983 s_edge. push (edge);
984 s_maxedge. push (maxedge);
985
986 // set the new vertex
987 vertex = next;
988
989 // mark the new vertex as visited
990 tab [vertex] = color;
991
992 // determine the edges to be visited
993 edge = vertex ? edgeEnds [vertex - 1] :
994 static_cast<int_t> (0);
995 maxedge = edgeEnds [vertex];
996 }
997 }
998} /* diGraph::DFScolorStack */
999
1000template <class wType> template <class Table, class Color>
1001inline void diGraph<wType>::DFScolor (Table &tab, const Color &color,
1002 int_t vertex) const
1003{
1004 DFScolorStack (tab, color, vertex);
1005 return;
1006} /* diGraph::DFScolor */
1007
1008// --------------------------------------------------
1009
1010template <class wType> template <class Table>
1012 int_t vertex, int_t &counter) const
1013{
1014 // mark the current vertex as visited
1015 tab [vertex] = -1;
1016
1017 // call DFS for the other vertices
1018 for (int_t edge = vertex ? edgeEnds [vertex - 1] :
1019 static_cast<int_t> (0);
1020 edge < edgeEnds [vertex]; ++ edge)
1021 {
1022 int_t next = edges [edge];
1023 if (!tab [next])
1024 DFSfinishTimeRecurrent (tab, next, counter);
1025 }
1026
1027 // record the finishing time for the current vertex and return
1028 tab [vertex] = ++ counter;
1029 return;
1030} /* diGraph::DFSfinishTimeRecurrent */
1031
1032template <class wType> template <class Table>
1033inline void diGraph<wType>::DFSfinishTimeStack (Table &tab, int_t vertex,
1034 int_t &counter) const
1035{
1036 // prepare stacks for the recursion
1037 std::stack<int_t> s_vertex;
1038 std::stack<int_t> s_edge;
1039 std::stack<int_t> s_maxedge;
1040
1041 // mark the current vertex as visited
1042 tab [vertex] = -1;
1043
1044 // determine the edges to be visited
1045 int_t edge = vertex ? edgeEnds [vertex - 1] :
1046 static_cast<int_t> (0);
1047 int_t maxedge = edgeEnds [vertex];
1048
1049 while (1)
1050 {
1051 // return to the previous recursion level
1052 // if all the edges have been followed
1053 if (edge >= maxedge)
1054 {
1055 // record the finishing time
1056 // for the current vertex
1057 tab [vertex] = ++ counter;
1058
1059 // return if this is the initial recursion level
1060 if (s_vertex. empty ())
1061 return;
1062
1063 // restore the variables from the previous level
1064 vertex = s_vertex. top ();
1065 s_vertex. pop ();
1066 edge = s_edge. top ();
1067 s_edge. pop ();
1068 maxedge = s_maxedge. top ();
1069 s_maxedge. pop ();
1070 continue;
1071 }
1072
1073 // go to the deeper recursion level if possible
1074 int_t next = edges [edge ++];
1075 if (!tab [next])
1076 {
1077 // store the previous variables at the stacks
1078 s_vertex. push (vertex);
1079 s_edge. push (edge);
1080 s_maxedge. push (maxedge);
1081
1082 // set the new vertex
1083 vertex = next;
1084
1085 // mark the new vertex as visited
1086 tab [vertex] = -1;
1087
1088 // determine the edges to be visited
1089 edge = vertex ? edgeEnds [vertex - 1] :
1090 static_cast<int_t> (0);
1091 maxedge = edgeEnds [vertex];
1092 }
1093 }
1094
1095 return;
1096} /* diGraph::DFSfinishTimeStack */
1097
1098template <class wType> template <class Table>
1099inline void diGraph<wType>::DFSfinishTime (Table &tab) const
1100{
1101 // initialize the table and the counter
1102 for (int_t i = 0; i < nVertices; ++ i)
1103 tab [i] = 0;
1104 int_t counter = 0;
1105
1106 // compute the finishing time for each tree in the DFS forest
1107 for (int_t i = 0; i < nVertices; ++ i)
1108 {
1109 if (!tab [i])
1110 DFSfinishTimeStack (tab, i, counter);
1111 }
1112
1113 #ifdef DIGRAPH_DEBUG
1114 int_t *tabdebug = new int_t [nVertices];
1115 for (int_t i = 0; i < nVertices; ++ i)
1116 tabdebug [i] = 0;
1117 int_t counterdebug = 0;
1118 for (int_t i = 0; i < nVertices; ++ i)
1119 if (!tabdebug [i])
1120 DFSfinishTimeRecurrent (tabdebug, i, counterdebug);
1121 if (counter != counterdebug)
1122 throw "DFSfinishTime: Wrong counter.";
1123 for (int_t i = 0; i < nVertices; ++ i)
1124 {
1125 if (tab [i] != tabdebug [i])
1126 {
1127 sbug << "\nDFSfinishTime error: tabRec [" << i <<
1128 "] = " << tab [i] << ", tabStack [" << i <<
1129 "] = " << tabdebug [i] << ".\n";
1130 throw "DFSfinishTime: Wrong numbers.";
1131 }
1132 }
1133 sbug << "DEBUG: DFSfinishTime OK. ";
1134 #endif // DIGRAPH_DEBUG
1135 return;
1136} /* diGraph::DFSfinishTime */
1137
1138// --------------------------------------------------
1139
1140template <class wType> template <class Table1, class Table2>
1141inline bool diGraph<wType>::DFSforestRecurrent (Table1 &tab, Table1 &ntab,
1142 int_t vertex, int_t treeNumber, int_t countTrees,
1143 Table2 &compVertices, int_t &curVertex,
1144 diGraph<wType> *sccGraph, int_t *sccEdgeAdded) const
1145{
1146 // add the vertex to the tree
1147 compVertices [curVertex ++] = vertex;
1148
1149 // mark the vertex as belonging to the current tree
1150 tab [vertex] = treeNumber;
1151// if (sccGraph)
1152// ntab [treeNumber - 1] = countTrees;
1153
1154 // build the tree recursively or record connections
1155 bool loop = false;
1156 for (int_t edge = vertex ? edgeEnds [vertex - 1] :
1157 static_cast<int_t> (0);
1158 edge < edgeEnds [vertex]; ++ edge)
1159 {
1160 int_t next = edges [edge];
1161 if (!tab [next])
1162 loop |= DFSforestRecurrent (tab, ntab, next,
1163 treeNumber, countTrees, compVertices,
1164 curVertex, sccGraph, sccEdgeAdded);
1165 else if (tab [next] == treeNumber)
1166 {
1167 if (sccGraph)
1168 {
1169 int_t target = ntab [treeNumber - 1];
1170 if (sccEdgeAdded [target] != treeNumber)
1171 {
1172 sccGraph -> addEdge (target);
1173 sccEdgeAdded [target] = treeNumber;
1174 }
1175 }
1176 loop = true;
1177 }
1178 else if (sccGraph)
1179 {
1180 int_t target = ntab [tab [next] - 1];
1181 if ((target >= 0) &&
1182 (sccEdgeAdded [target] != treeNumber))
1183 {
1184 sccGraph -> addEdge (target);
1185 sccEdgeAdded [target] = treeNumber;
1186 }
1187 }
1188 }
1189
1190 return loop;
1191} /* diGraph::DFSforestRecurrent */
1192
1193template <class wType> template <class Table1, class Table2>
1194inline bool diGraph<wType>::DFSforestStack (Table1 &tab, Table1 &ntab,
1195 int_t vertex, int_t treeNumber, int_t /*countTrees*/,
1196 Table2 &compVertices, int_t &curVertex,
1197 diGraph<wType> *sccGraph, int_t *sccEdgeAdded) const
1198{
1199 // prepare stacks for the recursion
1200 std::stack<int_t> s_vertex;
1201 std::stack<int_t> s_edge;
1202 std::stack<int_t> s_maxedge;
1203 std::stack<bool> s_loop;
1204
1205 // add the vertex to the tree
1206 compVertices [curVertex ++] = vertex;
1207
1208 // mark the vertex as belonging to the current tree
1209 tab [vertex] = treeNumber;
1210// if (sccGraph)
1211// ntab [vertex] = countTrees;
1212
1213 // build the tree recursively or record connections
1214 bool loop = false;
1215 int_t edge = vertex ? edgeEnds [vertex - 1] :
1216 static_cast<int_t> (0);
1217 int_t maxedge = edgeEnds [vertex];
1218 while (1)
1219 {
1220 // return to the previous recursion level
1221 // if all the edges have been followed
1222 if (edge >= maxedge)
1223 {
1224 // return if this is the initial recursion level
1225 if (s_vertex. empty ())
1226 return loop;
1227
1228 // restore the variables from the previous level
1229 vertex = s_vertex. top ();
1230 s_vertex. pop ();
1231 edge = s_edge. top ();
1232 s_edge. pop ();
1233 maxedge = s_maxedge. top ();
1234 s_maxedge. pop ();
1235 loop |= s_loop. top ();
1236 s_loop. pop ();
1237 continue;
1238 }
1239
1240 // go to the deeper recursion level if possible
1241 int_t next = edges [edge ++];
1242 if (!tab [next])
1243 {
1244 // store the previous variables at the stacks
1245 s_vertex. push (vertex);
1246 s_edge. push (edge);
1247 s_maxedge. push (maxedge);
1248 s_loop. push (loop);
1249
1250 // set the new vertex
1251 vertex = next;
1252
1253 // add the vertex to the tree
1254 compVertices [curVertex ++] = vertex;
1255
1256 // mark the vertex as belonging to the current tree
1257 tab [vertex] = treeNumber;
1258
1259 // determine the edges to be visited
1260 loop = false;
1261 edge = vertex ? edgeEnds [vertex - 1] :
1262 static_cast<int_t> (0);
1263 maxedge = edgeEnds [vertex];
1264 }
1265 else if (tab [next] == treeNumber)
1266 {
1267 if (sccGraph)
1268 {
1269 int_t target = ntab [treeNumber - 1];
1270 if (sccEdgeAdded [target] != treeNumber)
1271 {
1272 sccGraph -> addEdge (target);
1273 sccEdgeAdded [target] = treeNumber;
1274 }
1275 }
1276 loop = true;
1277 }
1278 else if (sccGraph)
1279 {
1280 int_t target = ntab [tab [next] - 1];
1281 if ((target >= 0) &&
1282 (sccEdgeAdded [target] != treeNumber))
1283 {
1284 sccGraph -> addEdge (target);
1285 sccEdgeAdded [target] = treeNumber;
1286 }
1287 }
1288 }
1289
1290 return loop;
1291} /* diGraph::DFSforestStack */
1292
1293template <class wType> template <class Table1, class Table2, class Table3>
1294inline int_t diGraph<wType>::DFSforest (const Table1 &ordered,
1295 Table2 &compVertices, Table3 &compEnds, bool nontrivial,
1296 diGraph<wType> *sccGraph) const
1297{
1298 // prepare a table to record the numbers of DFS trees
1299 // to which the vertices belong (the tree numbers begin with 1)
1300 int_t *tab = new int_t [nVertices];
1301 for (int_t i = 0; i < nVertices; ++ i)
1302 tab [i] = 0;
1303
1304 // prepare a table to record the numbers of nontrivial trees
1305 // that correspond to the trees in 'tab' (these numbers begin with 0)
1306 int_t *ntab = new int_t [nVertices];
1307
1308 // prepare a table to record the numbers of edges already in the
1309 // scc graph; "sccEdgeAdded [n] = m" indicates that the edge
1310 // m -> n has been added to the scc graph
1311 int_t *sccEdgeAdded = sccGraph ? new int_t [nVertices] :
1312 static_cast<int_t *> (0);
1313 if (sccGraph)
1314 {
1315 for (int_t n = 0; n < nVertices; ++ n)
1316 sccEdgeAdded [n] = -1;
1317 }
1318
1319 // prepare the official DFS tree number
1320 int_t treeNumber = 0;
1321
1322 // prepare the data for keeping the nontrivial trees information
1323 int_t countTrees = 0;
1324 int_t curVertex = 0;
1325
1326 // compute the DFS trees and connections between them
1327 for (int_t i = 0; i < nVertices; ++ i)
1328 {
1329 // take the next vertex
1330 int_t vertex = ordered [i];
1331
1332 // if the vertex already belongs to some tree, skip it
1333 if (tab [vertex])
1334 continue;
1335
1336 // add a vertex corresponding to the component
1337 if (sccGraph)
1338 sccGraph -> addVertex ();
1339
1340 // remember the previous vertex number
1341 int_t prevVertex = curVertex;
1342
1343 // mark the entire component and record connections graph
1344 if (sccGraph)
1345 ntab [treeNumber] = countTrees;
1346 ++ treeNumber;
1347 bool loop = DFSforestStack (tab, ntab, vertex,
1348 treeNumber, countTrees, compVertices,
1349 curVertex, sccGraph, sccEdgeAdded);
1350
1351 // update the index bound for the vertex list
1352 compEnds [countTrees ++] = curVertex;
1353
1354 // remove the component if it is trivial
1355 if (nontrivial && !loop)
1356 {
1357 -- countTrees;
1358 curVertex = prevVertex;
1359 if (sccGraph)
1360 {
1361 ntab [treeNumber - 1] = -1;
1362 sccGraph -> removeVertex ();
1363 }
1364 }
1365 }
1366
1367 #ifdef DIGRAPH_DEBUG
1368 diGraph<wType> *sccGraphdebug = 0;
1369 if (sccGraph)
1370 sccGraphdebug = new diGraph<wType>;
1371 // prepare a table to record the numbers of DFS trees
1372 // to which the vertices belong (the tree numbers begin with 1)
1373 int_t *tabdebug = new int_t [nVertices];
1374 for (int_t i = 0; i < nVertices; ++ i)
1375 tabdebug [i] = 0;
1376
1377 // prepare a table to record the numbers of nontrivial trees
1378 // to which the vertices belong (the tree numbers begin with 0)
1379 int_t *ntabdebug = new int_t [nVertices];
1380
1381 // prepare a table to record the numbers of vertices from which
1382 // edges were added to the scc graph
1383 int_t *sccEdgeAddeddebug = sccGraph ? new int_t [nVertices] :
1384 static_cast<int_t> (0);
1385 if (sccGraph)
1386 {
1387 for (int_t n = 0; n < nVertices; ++ n)
1388 sccEdgeAddeddebug [n] = -1;
1389 }
1390 // prepare the official DFS tree number
1391 int_t treeNumberdebug = 0;
1392
1393 // prepare the data for keeping the nontrivial trees information
1394 int_t countTreesdebug = 0;
1395 int_t curVertexdebug = 0;
1396
1397 int_t *compVerticesdebug = new int_t [nVertices];
1398 int_t *compEndsdebug = new int_t [nVertices];
1399
1400 // compute the DFS trees and connections between them
1401 for (int_t i = 0; i < nVertices; ++ i)
1402 {
1403 // take the next vertex
1404 int_t vertex = ordered [i];
1405
1406 // if the vertex already belongs to some tree, skip it
1407 if (tabdebug [vertex])
1408 continue;
1409
1410 // add a vertex corresponding to the component
1411 if (sccGraphdebug)
1412 sccGraphdebug -> addVertex ();
1413
1414 // remember the previous vertex number
1415 int_t prevVertex = curVertexdebug;
1416
1417 // mark the entire component and record connections graph
1418 if (sccGraphdebug)
1419 ntabdebug [treeNumberdebug] = countTreesdebug;
1420 ++ treeNumberdebug;
1421 bool loop = DFSforestRecurrent (tabdebug, ntabdebug, vertex,
1422 treeNumberdebug, countTreesdebug, compVerticesdebug,
1423 curVertexdebug, sccGraphdebug, sccEdgeAddeddebug);
1424
1425 // update the index bound for the vertex list
1426 compEndsdebug [countTreesdebug ++] = curVertexdebug;
1427
1428 // remove the component if it is trivial
1429 if (nontrivial && !loop)
1430 {
1431 -- countTreesdebug;
1432 curVertexdebug = prevVertex;
1433 if (sccGraphdebug)
1434 {
1435 ntabdebug [treeNumberdebug - 1] = -1;
1436 sccGraphdebug -> removeVertex ();
1437 }
1438 }
1439 }
1440 if (countTrees != countTreesdebug)
1441 throw "DFSforest: Wrong countTrees.";
1442 for (int_t i = 0; i < countTrees; ++ i)
1443 if (compEnds [i] != compEndsdebug [i])
1444 throw "DFSforest: Wrong compEnds.";
1445 for (int_t i = 0; i < compEndsdebug [countTrees - 1]; ++ i)
1446 if (compVertices [i] != compVerticesdebug [i])
1447 throw "DFSforest: Wrong vertices.";
1448 if (curVertex != curVertexdebug)
1449 throw "DFSforest: Wrong curVertex.";
1450 for (int_t i = 0; i < nVertices; ++ i)
1451 if (tab [i] != tabdebug [i])
1452 throw "DFSforest: Wrong tab.";
1453 if (sccGraph)
1454 {
1455 for (int_t i = 0; i < nVertices; ++ i)
1456 if (ntab [i] != ntabdebug [i])
1457 throw "DFSforest: Wrong ntab.";
1458 if (*sccGraph != *sccGraphdebug)
1459 throw "DFSforest: Wrong graph.";
1460 }
1461 if (sccEdgeAdded)
1462 {
1463 for (int_t i = 0; i < nVertices; ++ i)
1464 if (sccEdgeAdded [i] != sccEdgeAddeddebug [i])
1465 throw "DFSforest: Wrong sccEdgeAdded.";
1466 }
1467 if (treeNumber != treeNumberdebug)
1468 throw "DFSforest: Wrong treeNumber.";
1469 sbug << "DEBUG: DFSforest OK. ";
1470 if (!sccGraph)
1471 sbug << "(Graphs not compared.) ";
1472 delete [] compVerticesdebug;
1473 delete [] compEndsdebug;
1474 if (sccGraphdebug)
1475 delete sccGraphdebug;
1476 delete [] ntabdebug;
1477 delete [] tabdebug;
1478 if (sccEdgeAddeddebug)
1479 delete [] sccEdgeAddeddebug;
1480 #endif // DIGRAPH_DEBUG
1481
1482 if (sccEdgeAdded)
1483 delete [] sccEdgeAdded;
1484 delete [] ntab;
1485 delete [] tab;
1486 return countTrees;
1487} /* diGraph::DFSforest */
1488
1489template <class wType>
1490inline int_t diGraph<wType>::shortestPath (int_t source, int_t destination)
1491 const
1492{
1493 // make sure that the given vertex is present in the graph
1494 if ((source < 0) || (source >= nVertices) ||
1495 (destination < 0) || (destination >= nVertices))
1496 {
1497 throw "diGraph - shortest path: Wrong vertex number.";
1498 }
1499
1500 // prepare an array of bits to store the information
1501 // on whether the given vertices have been visited or not
1502 BitField visited;
1503 visited. allocate (nVertices);
1504 visited. clearall (nVertices);
1505
1506 // prepare queues for the BFS algorithm
1507 std::queue<int_t> q_vertex;
1508 std::queue<int_t> q_depth;
1509
1510 // set the initial vertex
1511 int_t vertex = source;
1512 int_t depth = 0;
1513
1514 while (1)
1515 {
1516 // mark the current vertex as visited
1517 visited. set (vertex);
1518
1519 // determine the depth of the vertices that will be analyzed
1520 ++ depth;
1521
1522 // determine the edges to be checked
1523 int_t firstedge = vertex ? edgeEnds [vertex - 1] :
1524 static_cast<int_t> (0);
1525 int_t maxedge = edgeEnds [vertex];
1526
1527 // put all the unvisited destination vertices on the stack
1528 for (int_t edge = firstedge; edge < maxedge; ++ edge)
1529 {
1530 // determine the vertex pointed to by this edge
1531 int_t next = edges [edge];
1532
1533 // if this is the destination vertex then return
1534 // the shortest path length; note: this vertex
1535 // might be visited if checking a loop, so it is
1536 // important to check the destination first
1537 if (next == destination)
1538 {
1539 visited. free ();
1540 return depth;
1541 }
1542
1543 // if the vertex was already visited then skip it
1544 if (visited. test (next))
1545 continue;
1546
1547 // add the vertex to the queue
1548 q_vertex. push (next);
1549 q_depth. push (depth);
1550 }
1551
1552 // if there are no vertices whose neighbors are to be
1553 // analyzed and the destination vertex was not found
1554 // then there is no path to that vertex
1555 if (q_vertex. empty ())
1556 {
1557 visited. free ();
1558 return 0;
1559 }
1560
1561 // pick up a vertex stored in the queue
1562 vertex = q_vertex. front ();
1563 q_vertex. pop ();
1564 depth = q_depth. front ();
1565 q_depth. pop ();
1566 }
1567} /* diGraph::shortestPath */
1568
1569template <class wType>
1571{
1572 return shortestPath (origin, origin);
1573} /* diGraph::shortestLoop */
1574
1575template <class wType>
1576template <class lenTable, class weightsType, class roundType>
1577inline void diGraph<wType>::Dijkstra (const roundType &rounding,
1578 int_t source, lenTable &len, weightsType &edgeWeights) const
1579{
1580 // use the Fibonacci heap as a priority queue
1581 FibonacciHeap<posWeight> Q (nVertices);
1582
1583 // add the vertices to the heap with the initial shortest path
1584 // lengths: 0 to the source, plus infinity to all the others
1585 for (int_t v = 0; v < nVertices; ++ v)
1586 {
1587 posWeight w (0);
1588 if (v != source)
1589 w. setInfinity ();
1590 int_t number = Q. Insert (w);
1591 if (number != v)
1592 {
1593 throw "Wrong implementation of Fibonacci heap "
1594 "for this version of Dijkstra.";
1595 }
1596 }
1597
1598 // pick up vertices from the priority queue, record the length
1599 // of the shortest path to them, and modify the remaining paths
1600 for (int_t i = 0; i < nVertices; ++ i)
1601 {
1602 // extract the minimal vertex from the queue
1603 int_t minVertex = Q. Minimum ();
1604 posWeight minWeight = Q. ExtractMinimum ();
1605
1606 if (minWeight. isInfinity ())
1607 {
1608 len [minVertex] = -1;
1609 continue;
1610 }
1611 wType minValue = minWeight. getValue ();
1612 len [minVertex] = minValue;
1613
1614 // go through all the edges emanating from this vertex
1615 // and update the path lengths for the target vertices
1616 int_t edge = minVertex ? edgeEnds [minVertex - 1] :
1617 static_cast<int_t> (0);
1618 int_t maxEdge = edgeEnds [minVertex];
1619 for (; edge < maxEdge; ++ edge)
1620 {
1621 // determine the vertex at the other end of the edge
1622 int_t nextVertex = edges [edge];
1623
1624 // if the path that runs through the extracted
1625 // vertex is shorter, then make a correction
1626 const posWeight &nextWeight = Q. Value (nextVertex);
1627 wType newWeight = rounding. add_down (minValue,
1628 edgeWeights [edge]);
1629 if (newWeight < 0)
1630 newWeight = 0;
1631 if (nextWeight. isInfinity () ||
1632 (newWeight < nextWeight. getValue ()))
1633 {
1634 Q. DecreaseKey (nextVertex,
1635 posWeight (newWeight));
1636 }
1637 }
1638 }
1639 return;
1640} /* diGraph::Dijkstra */
1641
1642template <class wType>
1643template <class lenTable, class roundType>
1644inline void diGraph<wType>::Dijkstra (const roundType &rounding,
1645 int_t source, lenTable &len) const
1646{
1647 this -> Dijkstra (rounding, source, len, this -> weights);
1648 return;
1649} /* diGraph::Dijkstra */
1650
1651template <class wType>
1652template <class lenTable>
1653inline void diGraph<wType>::Dijkstra (int_t source, lenTable &len) const
1654{
1655 const dummyRounding<wType> rounding = dummyRounding<wType> ();
1656 this -> Dijkstra (rounding, source, len);
1657 return;
1658} /* diGraph::Dijkstra */
1659
1660template <class wType> template <class lenTable, class predTable,
1661 class roundType>
1662inline bool diGraph<wType>::BellmanFord (const roundType &rounding,
1663 int_t source, lenTable &len, wType *infinity, predTable pred) const
1664{
1665 // make sure the source vertex number is correct
1666 if ((source < 0) || (source >= nVertices))
1667 throw "Bellman-Ford: Wrong source vertex number.";
1668
1669 // prepare marks to indicate finite values (not "infinity")
1670 BitField finite;
1671 finite. allocate (nVertices);
1672 finite. clearall (nVertices);
1673 finite. set (source);
1674 len [source] = 0;
1675
1676 // count the negative vertices
1677 int_t countNegative = 0;
1678
1679 // set the initial predecessors
1680 for (int_t i = 0; i < nVertices; ++ i)
1681 pred [i] = -1;
1682
1683 // update the lenghts of the paths repeatedly (max nVertices times)
1684 bool noNegativeLoop = false;
1685 int_t counter = 0;
1686 for (; counter <= nVertices; ++ counter)
1687 {
1688 bool modified = false;
1689 int_t curEdge = 0;
1690 for (int_t vertex = 0; vertex < nVertices; ++ vertex)
1691 {
1692 int_t maxEdge = edgeEnds [vertex];
1693 if (!finite. test (vertex))
1694 {
1695 curEdge = maxEdge;
1696 continue;
1697 }
1698 for (; curEdge < maxEdge; ++ curEdge)
1699 {
1700 int_t next = edges [curEdge];
1701 wType newlen = rounding. add_down
1702 (len [vertex], weights [curEdge]);
1703 if (!finite. test (next))
1704 {
1705 finite. set (next);
1706 modified = true;
1707 len [next] = newlen;
1708 pred [next] = vertex;
1709 if (newlen < 0)
1710 ++ countNegative;
1711 }
1712 else if (newlen < len [next])
1713 {
1714 modified = true;
1715 if (!(len [next] < 0) &&
1716 (newlen < 0))
1717 {
1718 ++ countNegative;
1719 }
1720 len [next] = newlen;
1721 pred [next] = vertex;
1722 }
1723 }
1724 }
1725 if (countNegative == nVertices)
1726 {
1727 noNegativeLoop = false;
1728 ++ counter;
1729 break;
1730 }
1731 if (!modified)
1732 {
1733 noNegativeLoop = true;
1734 ++ counter;
1735 break;
1736 }
1737 }
1738
1739 // show a message on how many loops have been done
1740 if (false && chomp::homology::sbug. show)
1741 {
1742 chomp::homology::sbug << "Bellman-Ford: " <<
1743 counter << ((counter > 1) ? " loops (" : " loop (") <<
1744 nVertices << " vertices, " << countNegative <<
1745 " negative). " <<
1746 (noNegativeLoop ? "No negative loops.\n" :
1747 "A negative loop found.\n");
1748 }
1749
1750 // compute the value for the infinity and set the undefined distances
1751 if (infinity && noNegativeLoop)
1752 {
1753 wType infty (0);
1754 bool first = true;
1755 for (int_t i = 0; i < nVertices; ++ i)
1756 {
1757 if (!finite. test (i))
1758 continue;
1759 if (first)
1760 {
1761 infty = len [i];
1762 first = false;
1763 }
1764 else if (infty < len [i])
1765 {
1766 infty = len [i];
1767 }
1768 }
1769 infty = infty + 1;
1770 for (int_t i = 0; i < nVertices; ++ i)
1771 {
1772 if (!finite. test (i))
1773 len [i] = infty;
1774 }
1775 *infinity = infty;
1776 }
1777
1778 finite. free ();
1779 return noNegativeLoop;
1780} /* diGraph::BellmanFord */
1781
1782template <class wType> template <class lenTable, class predTable>
1783inline bool diGraph<wType>::BellmanFord (int_t source, lenTable &len,
1784 wType *infinity, predTable pred) const
1785{
1786 const dummyRounding<wType> rounding = dummyRounding<wType> ();
1787 return this -> BellmanFord (rounding, source, len, infinity, pred);
1788} /* diGraph::BellmanFord */
1789
1790template <class wType> template <class roundType>
1791inline bool diGraph<wType>::BellmanFord (const roundType &rounding,
1792 int_t source) const
1793{
1794 chomp::homology::auto_array<wType> len_ptr (new wType [nVertices]);
1795 wType *len = len_ptr. get ();
1796 wType *infinity = 0;
1797 dummyArray tab;
1798 return BellmanFord (rounding, source, len, infinity, tab);
1799} /* diGraph::BellmanFord */
1800
1801template <class wType>
1802inline bool diGraph<wType>::BellmanFord (int_t source) const
1803{
1804 const dummyRounding<wType> rounding = dummyRounding<wType> ();
1805 return BellmanFord (rounding, source);
1806} /* diGraph::BellmanFord */
1807
1808template <class wType>
1809inline wType diGraph<wType>::Edmonds () const
1810{
1811 // create a list of edges with weights and sort this list
1812 std::vector<edgeTriple> edgeTriples (countEdges ());
1813 int_t prevEdge = 0;
1814 int_t curEdge = 0;
1815 for (int_t vert = 0; vert < nVertices; ++ vert)
1816 {
1817 while (curEdge < edgeEnds [vert])
1818 {
1819 edgeTriple &e = edgeTriples [curEdge];
1820 e. vert1 = vert;
1821 e. vert2 = edges [curEdge];
1822 e. weight = weights [curEdge];
1823 ++ curEdge;
1824 }
1825 prevEdge = curEdge;
1826 }
1827 std::sort (edgeTriples. begin (), edgeTriples. end ());
1828
1829 // create a forest which initially contains single vertices
1830 chomp::homology::auto_array<int_t> root_ptr (new int_t [nVertices]);
1831 int_t *root = root_ptr. get ();
1832 for (int_t vert = 0; vert < nVertices; ++ vert)
1833 {
1834 root [vert] = -1;
1835 }
1836
1837 // go through the edges and join the trees, but avoid loops
1838 wType totalWeight = 0;
1839 int_t nEdges = countEdges ();
1840 for (int_t curEdge = 0; curEdge < nEdges; ++ curEdge)
1841 {
1842 // determine the roots of both vertices of the edge
1843 // and compress the paths
1844 edgeTriple &e = edgeTriples [curEdge];
1845 int_t root1 = e. vert1;
1846 while (root [root1] >= 0)
1847 {
1848 root1 = root [root1];
1849 }
1850 int_t vert1 = e. vert1;
1851 while (root [vert1] >= 0)
1852 {
1853 int_t next = root [vert1];
1854 root [vert1] = root1;
1855 vert1 = next;
1856 }
1857 int_t root2 = e. vert2;
1858 while (root [root2] >= 0)
1859 {
1860 root2 = root [root2];
1861 }
1862 int_t vert2 = e. vert2;
1863 while (root [vert2] >= 0)
1864 {
1865 int_t next = root [vert2];
1866 root [vert2] = root2;
1867 vert2 = next;
1868 }
1869
1870 // skip the edge if it closes a loop
1871 if (root1 == root2)
1872 continue;
1873
1874 // add the weight
1875 totalWeight += e. weight;
1876
1877 // join the trees
1878 root [root1] = root2;
1879 }
1880 return totalWeight;
1881} /* diGraph::Edmonds */
1882
1883template <class wType>
1884inline wType diGraph<wType>::EdmondsOld () const
1885{
1886 // create a list of edges with weights and sort this list
1887 std::vector<edgeTriple> edgeTriples (countEdges ());
1888 int_t prevEdge = 0;
1889 int_t curEdge = 0;
1890 for (int_t vert = 0; vert < nVertices; ++ vert)
1891 {
1892 while (curEdge < edgeEnds [vert])
1893 {
1894 edgeTriple &e = edgeTriples [curEdge];
1895 e. vert1 = vert;
1896 e. vert2 = edges [curEdge];
1897 e. weight = weights [curEdge];
1898 ++ curEdge;
1899 }
1900 prevEdge = curEdge;
1901 }
1902 std::sort (edgeTriples. begin (), edgeTriples. end ());
1903
1904 // create a forest which initially contains single vertices
1906 (new int_t [nVertices]);
1907 int_t *forest = forest_ptr. get ();
1909 (new int_t [nVertices]);
1910 int_t *next = next_ptr. get ();
1912 (new int_t [nVertices]);
1913 int_t *prev = prev_ptr. get ();
1914 for (int_t vert = 0; vert < nVertices; ++ vert)
1915 {
1916 forest [vert] = vert;
1917 next [vert] = -1;
1918 prev [vert] = -1;
1919 }
1920
1921 // go through the edges and join the trees, but avoid loops
1922 wType totalWeight = 0;
1923 int_t nEdges = countEdges ();
1924 for (int_t curEdge = 0; curEdge < nEdges; ++ curEdge)
1925 {
1926 // check the edge and skip it if it closes a loop
1927 edgeTriple &e = edgeTriples [curEdge];
1928 if (forest [e. vert1] == forest [e. vert2])
1929 continue;
1930
1931 // add the weight
1932 totalWeight += e. weight;
1933
1934 // go to the end of the first tree
1935 int_t vert1 = e. vert1;
1936 while (next [vert1] >= 0)
1937 {
1938 vert1 = next [vert1];
1939 }
1940
1941 // go to the beginning of the second tree
1942 int_t vert2 = e. vert2;
1943 while (prev [vert2] >= 0)
1944 {
1945 vert2 = prev [vert2];
1946 }
1947
1948 // join the trees and modify the numbers
1949 next [vert1] = vert2;
1950 prev [vert2] = vert1;
1951 int_t treeNumber = forest [vert1];
1952 while (vert2 >= 0)
1953 {
1954 forest [vert2] = treeNumber;
1955 vert2 = next [vert2];
1956 }
1957 }
1958 return totalWeight;
1959} /* diGraph::EdmondsOld */
1960
1961template <class wType>
1962template <class arrayType, class roundType>
1963inline wType diGraph<wType>::FloydWarshall (const roundType &rounding,
1964 arrayType &arr, bool setInfinity, bool ignoreNegLoop) const
1965{
1966 // do nothing if the graph is empty
1967 if (!nVertices)
1968 return 0;
1969
1970 // prepare marks to indicate finite values (not "infinity")
1971 BitField *finite = new BitField [nVertices];
1972 for (int_t i = 0; i < nVertices; ++ i)
1973 {
1974 finite [i]. allocate (nVertices);
1975 finite [i]. clearall (nVertices);
1976 }
1977
1978 // create the initial values of the array based on the edge weights
1979 int_t curEdge = 0;
1980 for (int_t source = 0; source < nVertices; ++ source)
1981 {
1982 bool diagset = false;
1983 while (curEdge < edgeEnds [source])
1984 {
1985 int_t target = edges [curEdge];
1986 const wType &weight = weights [curEdge];
1987 if (source == target)
1988 {
1989 if (weight < 0)
1990 {
1991 arr [source] [target] = weight;
1992 diagset = true;
1993 }
1994 }
1995 else
1996 {
1997 arr [source] [target] = weight;
1998 finite [source]. set (target);
1999 }
2000 ++ curEdge;
2001 }
2002 if (!diagset)
2003 arr [source] [source] = 0;
2004 finite [source]. set (source);
2005 }
2006
2007 // find the shortest paths between the vertices (dynamic programming)
2008 for (int_t k = 0; k < nVertices; ++ k)
2009 {
2010 for (int_t i = 0; i < nVertices; ++ i)
2011 {
2012 if (!finite [i]. test (k))
2013 continue;
2014 for (int_t j = 0; j < nVertices; ++ j)
2015 {
2016 if (!finite [k]. test (j))
2017 continue;
2018 const wType sum = rounding. add_down
2019 (arr [i] [k], arr [k] [j]);
2020 if (finite [i]. test (j))
2021 {
2022 if (sum < arr [i] [j])
2023 arr [i] [j] = sum;
2024 }
2025 else
2026 {
2027 arr [i] [j] = sum;
2028 finite [i]. set (j);
2029 }
2030 }
2031 }
2032 }
2033
2034 // verify if a negative loop exists by checking for a negative
2035 // result in the diagonal
2036 if (!ignoreNegLoop)
2037 {
2038 for (int_t i = 0; i < nVertices; ++ i)
2039 {
2040 if (arr [i] [i] < 0)
2041 throw "Negative loop in Floyd-Warshall.";
2042 }
2043 }
2044
2045 // prepare a variable to store the returned result
2046 wType result = 0;
2047
2048 // compute the value for the infinity and fill in the array
2049 // if requested to do so
2050 if (setInfinity)
2051 {
2052 wType &infinity = result;
2053 for (int_t i = 0; i < nVertices; ++ i)
2054 {
2055 for (int_t j = 0; j < nVertices; ++ j)
2056 {
2057 if (finite [i]. test (j) &&
2058 (infinity <= arr [i] [j]))
2059 {
2060 infinity = rounding. add_up
2061 (arr [i] [j], 1);
2062 }
2063 }
2064 }
2065 for (int_t i = 0; i < nVertices; ++ i)
2066 {
2067 for (int_t j = 0; j < nVertices; ++ j)
2068 {
2069 if (!finite [i]. test (j))
2070 arr [i] [j] = infinity;
2071 }
2072 }
2073 }
2074
2075 // otherwise, only compute the minimum path weight
2076 else
2077 {
2078 wType &minWeight = result;
2079 bool firstTime = true;
2080 for (int_t i = 0; i < nVertices; ++ i)
2081 {
2082 for (int_t j = 0; j < nVertices; ++ j)
2083 {
2084 if (finite [i]. test (j))
2085 {
2086 if (firstTime)
2087 {
2088 minWeight = arr [i] [j];
2089 firstTime = false;
2090 }
2091 else if (arr [i] [j] < minWeight)
2092 {
2093 minWeight = arr [i] [j];
2094 }
2095 }
2096 }
2097 }
2098 }
2099
2100 // release the 'finite' bitfields
2101 for (int_t i = 0; i < nVertices; ++ i)
2102 finite [i]. free ();
2103 delete [] finite;
2104
2105 return result;
2106} /* diGraph::FloydWarshall */
2107
2108template <class wType>
2109template <class arrayType>
2110inline wType diGraph<wType>::FloydWarshall (arrayType &arr,
2111 bool setInfinity, bool ignoreNegLoop) const
2112{
2113 const dummyRounding<wType> rounding = dummyRounding<wType> ();
2114 return FloydWarshall (rounding, arr, setInfinity, ignoreNegLoop);
2115} /* diGraph::FloydWarshall */
2116
2117template <class wType>
2118template <class arrayType, class roundType>
2119inline wType diGraph<wType>::Johnson (const roundType &rounding,
2120 arrayType &arr, bool setInfinity, bool ignoreNegLoop) const
2121{
2122 // DEBUG VERIFICATION
2123 if (false && sbug. show)
2124 {
2125 timeused stopWatch;
2126 wType res = FloydWarshall (rounding,
2127 arr, setInfinity, ignoreNegLoop);
2128 chomp::homology::sbug << "\n[Floyd-Warshall: " << res <<
2129 ", " << (double) stopWatch << " sec]\n";
2130 }
2131 // debug time measurement (see below)
2132// timeused stopWatch;
2133
2134 // do nothing if the graph is empty
2135 if (!nVertices)
2136 return 0;
2137
2138 // STEP 1: Compute the shortest paths to any vertex from an
2139 // artificial extra vertex connected to every other vertex in the
2140 // graph by an edge of weight zero. Use Bellman-Ford for this.
2141 wType *len = new wType [nVertices];
2142 for (int_t i = 0; i < nVertices; ++ i)
2143 len [i] = 0;
2144
2145 // update the lenghts of the paths repeatedly (max nVertices times)
2146 bool noNegativeLoop = false;
2147 int_t counter = 0;
2148 for (; counter <= nVertices; ++ counter)
2149 {
2150 bool modified = false;
2151 int_t curEdge = 0;
2152 for (int_t vertex = 0; vertex < nVertices; ++ vertex)
2153 {
2154 int_t maxEdge = edgeEnds [vertex];
2155 for (; curEdge < maxEdge; ++ curEdge)
2156 {
2157 int_t next = edges [curEdge];
2158 wType newlen = rounding. add_down
2159 (len [vertex], weights [curEdge]);
2160 if (newlen < len [next])
2161 {
2162 // this "if" statement is necessary
2163 // because of a bug in GCC 3.4.2...
2164 if (counter > nVertices)
2165 {
2166 std::cout << vertex;
2167 }
2168 modified = true;
2169 len [next] = newlen;
2170 }
2171 }
2172 }
2173 if (!modified)
2174 {
2175 noNegativeLoop = true;
2176 ++ counter;
2177 break;
2178 }
2179 }
2180 if (!ignoreNegLoop && !noNegativeLoop)
2181 throw "Negative loop found in Johnson's algorithm.";
2182
2183 // STEP 2: Re-weigh the edges using the computed path lengths.
2184 wType *newWeights = new wType [edgeEnds [nVertices - 1]];
2185 int_t edge = 0;
2186 for (int_t vertex = 0; vertex < nVertices; ++ vertex)
2187 {
2188 int_t maxEdge = edgeEnds [vertex];
2189 for (; edge < maxEdge; ++ edge)
2190 {
2191 wType w = weights [edge];
2192 w = rounding. add_down (w, len [vertex]);
2193 w = rounding. sub_down (w, len [edges [edge]]);
2194 newWeights [edge] = (w < 0) ?
2195 static_cast<wType> (0) : w;
2196 }
2197 }
2198
2199 // STEP 3: Run the Dijkstra algorithm for every vertex to compute
2200 // the shortest paths to all the other vertices.
2201 // Negative entries indicate no path existence.
2202 for (int_t u = 0; u < nVertices; ++ u)
2203 {
2204 this -> Dijkstra (rounding, u, arr [u], newWeights);
2205 }
2206 delete [] newWeights;
2207
2208 // STEP 4: Make a correction to the computed path lengths.
2209 // Compute the value for infinity if requested to.
2210 // Otherwise compute the minimum of path lengths.
2211 wType result = 0;
2212 if (setInfinity)
2213 {
2214 wType &infinity = result;
2215 for (int_t u = 0; u < nVertices; ++ u)
2216 {
2217 for (int_t v = 0; v < nVertices; ++ v)
2218 {
2219 wType w = arr [u] [v];
2220 if (w < 0)
2221 continue;
2222 w = rounding. add_down (w, len [v]);
2223 w = rounding. sub_down (w, len [u]);
2224 if (w < infinity)
2225 continue;
2226 infinity = rounding. add_up (w, 1);
2227 }
2228 }
2229 for (int_t u = 0; u < nVertices; ++ u)
2230 {
2231 for (int_t v = 0; v < nVertices; ++ v)
2232 {
2233 wType w = arr [u] [v];
2234 if (w < 0)
2235 {
2236 arr [u] [v] = infinity;
2237 continue;
2238 }
2239 w = rounding. add_down (w, len [v]);
2240 arr [u] [v] =
2241 rounding. sub_down (w, len [u]);
2242 }
2243 }
2244 }
2245 else
2246 {
2247 wType &minWeight = result;
2248 bool firstTime = true;
2249 for (int_t u = 0; u < nVertices; ++ u)
2250 {
2251 for (int_t v = 0; v < nVertices; ++ v)
2252 {
2253 wType w = arr [u] [v];
2254 if (w < 0)
2255 continue;
2256 w = rounding. add_down (w, len [v]);
2257 w = rounding. sub_down (w, len [u]);
2258 if (firstTime)
2259 {
2260 minWeight = w;
2261 firstTime = false;
2262 }
2263 else if (w < minWeight)
2264 minWeight = w;
2265 }
2266 }
2267 }
2268 delete [] len;
2269
2270 // DEBUG VERIFICATION
2271 if (false && sbug. show)
2272 {
2273// chomp::homology::sbug << "[Johnson: " << result <<
2274// ", " << (double) stopWatch << " sec]\n";
2275 }
2276
2277 return result;
2278} /* diGraph::Johnson */
2279
2280template <class wType>
2281template <class arrayType>
2282inline wType diGraph<wType>::Johnson (arrayType &arr,
2283 bool setInfinity, bool ignoreNegLoop) const
2284{
2285 const dummyRounding<wType> rounding = dummyRounding<wType> ();
2286 return Johnson (rounding, arr, setInfinity, ignoreNegLoop);
2287} /* diGraph::Johnson */
2288
2289template <class wType>
2290template <class roundType>
2291wType diGraph<wType>::minPathWeight (const roundType &rounding,
2292 bool ignoreNegLoop, int sparseGraph) const
2293{
2294 // if the graph is empty, return 0 as the minimum path weight
2295 if (nVertices <= 0)
2296 return 0;
2297
2298 // allocate memory for an array of arrays to store min path weights
2299 wType **arr = new wType * [nVertices];
2300 for (int_t i = 0; i < nVertices; ++ i)
2301 arr [i] = new wType [nVertices];
2302
2303 // determine whether to run the Floyd-Warshall algorithm
2304 // or Johnson's algorithm
2305 bool sparse = false;
2306 if (sparseGraph == 1)
2307 sparse = true;
2308 else if (sparseGraph != 0)
2309 {
2310 double nEdgesD = this -> countEdges ();
2311 double nVerticesD = this -> countVertices ();
2312 if ((nVerticesD > 3000) && (nEdgesD < nVerticesD * 1000) &&
2313 (nEdgesD < nVerticesD * nVerticesD / 50))
2314 {
2315 sparse = true;
2316 }
2317 }
2318
2319 // run the Johnson's or Floyd-Warshall algorithm
2320 wType minWeight = sparse ?
2321 this -> Johnson (rounding, arr, false, ignoreNegLoop) :
2322 this -> FloydWarshall (rounding, arr, false, ignoreNegLoop);
2323
2324/* // compute the minimum of all the paths
2325 wType minWeight = arr [0] [0];
2326 for (int_t i = 0; i < nVertices; ++ i)
2327 {
2328 for (int_t j = 0; j < nVertices; ++ j)
2329 {
2330 const wType &weight = arr [i] [j];
2331 if (weight < minWeight)
2332 minWeight = weight;
2333 }
2334 }
2335*/
2336 // release the memory
2337 for (int_t i = 0; i < nVertices; ++ i)
2338 delete [] (arr [i]);
2339 delete [] arr;
2340
2341 return minWeight;
2342} /* diGraph::minPathWeight */
2343
2344template <class wType>
2345wType diGraph<wType>::minPathWeight (bool ignoreNegLoop, int sparseGraph)
2346 const
2347{
2348 const dummyRounding<wType> rounding = dummyRounding<wType> ();
2349 return this -> minPathWeight (rounding, ignoreNegLoop, sparseGraph);
2350} /* diGraph::minPathWeight */
2351
2352template <class wType> template <class outType>
2353inline outType &diGraph<wType>::show (outType &out, bool showWeights) const
2354{
2355 out << "; Directed graph: " << nVertices << " vertices.\n";
2356 int_t curEdge = 0;
2357 for (int_t i = 0; i < nVertices; ++ i)
2358 {
2359 for (; curEdge < edgeEnds [i]; ++ curEdge)
2360 {
2361 out << i << " -> " << edges [curEdge];
2362 if (showWeights)
2363 out << " [" << weights [curEdge] << "]\n";
2364 else
2365 out << "\n";
2366 }
2367 }
2368 out << "; This is the end of the graph.\n";
2369 return out;
2370} /* diGraph::show */
2371
2372
2373// --------------------------------------------------
2374
2376template <class wType>
2377inline std::ostream &operator << (std::ostream &out, const diGraph<wType> &g)
2378{
2379 return g. show (out, false);
2380} /* operator << */
2381
2382// --------------------------------------------------
2383
2391template <class wType, class Table1, class Table2>
2392inline int_t SCC (const diGraph<wType> &g, Table1 &compVertices,
2393 Table2 &compEnds, diGraph<wType> *scc = 0,
2394 diGraph<wType> *transposed = 0, bool copyweights = false)
2395{
2396 // prepare two tables
2397 int_t nVert = g. countVertices ();
2398 int_t *ordered = new int_t [nVert];
2399 int_t *tab = new int_t [nVert];
2400
2401 // compute the list of vertices in the descending finishing time
2402 g. DFSfinishTime (tab);
2403 for (int_t i = 0; i < nVert; ++ i)
2404 ordered [nVert - tab [i]] = i;
2405 delete [] tab;
2406
2407 // create the transposed graph
2408 diGraph<wType> gT;
2409 if (!transposed)
2410 transposed = &gT;
2411 g. transpose (*transposed, copyweights);
2412
2413 // extract the DFS forest of gT in the given order of vertices
2414 int_t n = transposed -> DFSforest (ordered, compVertices, compEnds,
2415 true, scc);
2416
2417 // cleanup memory and return the number of components
2418 delete [] ordered;
2419 return n;
2420} /* SCC */
2421
2422// --------------------------------------------------
2423
2433template <class wType, class Table1, class Table2>
2434inline int_t SCC_Tarjan (const diGraph<wType> &g, Table1 &compVertices,
2435 Table2 &compEnds)
2436{
2437 // return the obvious result if the graph is empty
2438 int_t nVertices = g. countVertices ();
2439 if (!nVertices)
2440 return 0;
2441
2442 // prepare an array of discovery times for all the vertices
2443 // (zero == not yet discovered)
2444 std::vector<int_t> dfsIndex (nVertices, 0);
2445
2446 // prepare an array of the minimal index of a node reachable
2447 // from each of the vertices
2448 std::vector<int_t> lowLink (nVertices, 0);
2449
2450 // prepare an empty stack of nodes
2451 std::stack<int_t> s_nodes;
2452
2453 // prepare an array of bits indicating whether the vertices are
2454 // in the stack of nodes or not
2455 BitField inTheStack;
2456 inTheStack. allocate (nVertices);
2457 inTheStack. clearall (nVertices);
2458
2459 // prepare the number of strongly connected components
2460 int_t nComponents = 0;
2461
2462 // prepare the current position in the array 'compVertices'
2463 int_t posVertices = 0;
2464
2465 // remember the next vertex number in the graph to scan
2466 // whether this vertex has already been visited or not
2467 int_t vertexToScan = 0;
2468
2469 // prepare a variable for storing the discovery time in the DFS
2470 int_t discoveryTime = 0;
2471
2472 // prepare stacks for the DFS recursion
2473 std::stack<int_t> s_vertex;
2474 std::stack<int_t> s_edge;
2475 std::stack<int_t> s_maxedge;
2476
2477 // initialize the number of the currently processed vertex
2478 int_t vertex = -1;
2479
2480 // initialize the range of edges to be visited
2481 int_t edge = 0;
2482 int_t maxedge = 0;
2483
2484 while (1)
2485 {
2486 // return to the previous recursion level
2487 // if all the edges have been checked
2488 if (edge >= maxedge)
2489 {
2490 // extract a strongly connected component
2491 if ((vertex >= 0) && (lowLink [vertex] ==
2492 dfsIndex [vertex]))
2493 {
2494 int_t v = 0;
2495 do
2496 {
2497 v = s_nodes. top ();
2498 s_nodes. pop ();
2499 inTheStack. clear (v);
2500 compVertices [posVertices ++] = v;
2501 } while (v != vertex);
2502 compEnds [nComponents ++] = posVertices;
2503 }
2504
2505 // if this is the top level of the recursion
2506 // then find another unvisited vertex or return
2507 if (s_vertex. empty ())
2508 {
2509 // find an unvisited vertex in the graph
2510 while ((vertexToScan < nVertices) &&
2511 (dfsIndex [vertexToScan] != 0))
2512 {
2513 ++ vertexToScan;
2514 }
2515
2516 // return the result if all visited
2517 if (vertexToScan == nVertices)
2518 {
2519 inTheStack. free ();
2520 return nComponents;
2521 }
2522
2523 // set the new vertex
2524 vertex = vertexToScan ++;
2525
2526 // mark the current vertex as visited
2527 // and initialize its low link
2528 dfsIndex [vertex] = ++ discoveryTime;
2529 lowLink [vertex] = discoveryTime;
2530
2531 // push this vertex on the stack
2532 s_nodes. push (vertex);
2533 inTheStack. set (vertex);
2534
2535 // determine the edges to be visited
2536 edge = 0;
2537 maxedge = g. countEdges (vertex);
2538 }
2539
2540 // otherwise trace back to the previous level
2541 else
2542 {
2543 // remember the current low link index
2544 int_t lowLink2 = lowLink [vertex];
2545
2546 // restore the variables
2547 vertex = s_vertex. top ();
2548 s_vertex. pop ();
2549 edge = s_edge. top ();
2550 s_edge. pop ();
2551 maxedge = s_maxedge. top ();
2552 s_maxedge. pop ();
2553
2554 // update the current low link index
2555 if (lowLink [vertex] > lowLink2)
2556 lowLink [vertex] = lowLink2;
2557 }
2558 }
2559
2560 // analyse the next edge coming out from the current vertex
2561 else
2562 {
2563 // determine the next vertex
2564 int_t next = g. getEdge (vertex, edge ++);
2565
2566 // go to a deeper recursion level if unvisited
2567 if (dfsIndex [next] == 0)
2568 {
2569 // store the variables at the stacks
2570 s_vertex. push (vertex);
2571 s_edge. push (edge);
2572 s_maxedge. push (maxedge);
2573
2574 // set the new vertex
2575 vertex = next;
2576
2577 // mark the new vertex as visited
2578 dfsIndex [vertex] = ++ discoveryTime;
2579 lowLink [vertex] = discoveryTime;
2580
2581 // push this vertex on the stack
2582 s_nodes. push (vertex);
2583 inTheStack. set (vertex);
2584
2585 // determine the edges to be visited
2586 edge = 0;
2587 maxedge = g. countEdges (vertex);
2588 }
2589
2590 // update the low link index if the vertex has been
2591 // visited and is currently in the stack of nodes
2592 else if (inTheStack. test (next))
2593 {
2594 if (lowLink [vertex] > dfsIndex [next])
2595 lowLink [vertex] = dfsIndex [next];
2596 }
2597 }
2598 }
2599
2600 // finalize and return the number of strongly connected components
2601 inTheStack. free ();
2602 return nComponents;
2603} /* SCC_Tarjan */
2604
2605// --------------------------------------------------
2606
2607template <class wType>
2609{
2610 // find the strongly connected components of the graph
2611 multitable<int_t> compVertices, compEnds;
2612 bool copyweights = !!transposed;
2613 int_t countSCC = SCC (*this, compVertices, compEnds,
2614 static_cast<diGraph<wType> *> (0), transposed, copyweights);
2615 if (countSCC <= 0)
2616 return 0;
2617
2618 // compute the maximum size of each strongly connected component
2619 int_t maxCompSize = compEnds [0];
2620 for (int_t comp = 1; comp < countSCC; ++ comp)
2621 {
2622 int_t compSize = compEnds [comp] - compEnds [comp - 1];
2623 if (maxCompSize < compSize)
2624 maxCompSize = compSize;
2625 }
2626
2627 // allocate arrays for weights and bit fields
2628 wType **F = new wType * [maxCompSize + 1];
2629 BitField *finite = new BitField [maxCompSize + 1];
2630 for (int_t i = 0; i <= maxCompSize; ++ i)
2631 {
2632 F [i] = new wType [maxCompSize];
2633 finite [i]. allocate (maxCompSize);
2634 }
2635
2636 // compute the numbers of vertices in each component
2637 int_t *numbers = new int_t [nVertices];
2638 int_t *components = new int_t [nVertices];
2639 for (int_t i = 0; i < nVertices; ++ i)
2640 components [i] = -1;
2641 int_t offset = 0;
2642 for (int_t comp = 0; comp < countSCC; ++ comp)
2643 {
2644 int_t maxOffset = compEnds [comp];
2645 int_t pos = offset;
2646 for (; pos < maxOffset; ++ pos)
2647 {
2648 numbers [compVertices [pos]] = pos - offset;
2649 components [compVertices [pos]] = comp;
2650 }
2651 offset = pos;
2652 }
2653
2654 // compute the minimum mean cycle weight for each component
2655 wType minWeight (0);
2656 for (int_t comp = 0; comp < countSCC; ++ comp)
2657 {
2658 int_t offset = comp ? compEnds [comp - 1] :
2659 static_cast<int_t> (0);
2660 int_t compSize = compEnds [comp] - offset;
2661 for (int_t i = 0; i <= compSize; ++ i)
2662 finite [i]. clearall (compSize);
2663 F [0] [0] = 0;
2664 finite [0]. set (0);
2665 // compute path progressions of given length
2666 for (int_t len = 1; len <= compSize; ++ len)
2667 {
2668 // process source vertices
2669 for (int_t i = 0; i < compSize; ++ i)
2670 {
2671 if (!finite [len - 1]. test (i))
2672 continue;
2673 wType prevWeight = F [len - 1] [i];
2674 int_t source = compVertices [offset + i];
2675
2676 // process target vertices (and edges)
2677 int_t edgeOffset = source ?
2678 edgeEnds [source - 1] :
2679 static_cast<int_t> (0);
2680 int_t edgeEnd = edgeEnds [source];
2681 for (; edgeOffset < edgeEnd; ++ edgeOffset)
2682 {
2683 int_t target = edges [edgeOffset];
2684 if (components [target] != comp)
2685 continue;
2686 int_t j = numbers [target];
2687 wType newWeight = prevWeight +
2688 weights [edgeOffset];
2689 if (!finite [len]. test (j))
2690 {
2691 finite [len]. set (j);
2692 F [len] [j] = newWeight;
2693 }
2694 else if (newWeight < F [len] [j])
2695 F [len] [j] = newWeight;
2696 }
2697 }
2698 }
2699
2700 // compute the minimum mean cycle weight for this component
2701 wType minCompWeight (0);
2702 bool firstMin = true;
2703 for (int_t vert = 0; vert < compSize; ++ vert)
2704 {
2705 if (!finite [compSize]. test (vert))
2706 continue;
2707 bool firstAverage = true;
2708 wType maxAverage = 0;
2709 for (int_t first = 0; first < compSize; ++ first)
2710 {
2711 if (!finite [first]. test (vert))
2712 continue;
2713 wType average = (F [compSize] [vert] -
2714 F [first] [vert]) /
2715 (compSize - first);
2716 if (firstAverage)
2717 {
2718 maxAverage = average;
2719 firstAverage = false;
2720 }
2721 else if (maxAverage < average)
2722 maxAverage = average;
2723 }
2724 if (firstMin || (maxAverage < minCompWeight))
2725 {
2726 if (firstAverage)
2727 throw "Bug in Karp's algorithm";
2728 minCompWeight = maxAverage;
2729 firstMin = false;
2730 }
2731 }
2732
2733 // make a correction to the total minimum if necessary
2734 if (!comp || (minCompWeight < minWeight))
2735 minWeight = minCompWeight;
2736 }
2737
2738 // release allocated memory
2739 delete [] components;
2740 delete [] numbers;
2741 for (int_t i = 0; i <= maxCompSize; ++ i)
2742 {
2743 finite [i]. free ();
2744 delete [] (F [i]);
2745 }
2746 delete [] finite;
2747 delete [] F;
2748
2749 // return the computed minimum
2750 return minWeight;
2751} /* diGraph::minMeanCycleWeight */
2752
2753template <class wType>
2754template <class roundType>
2755wType diGraph<wType>::minMeanCycleWeight (const roundType &rounding,
2756 diGraph<wType> *transposed) const
2757{
2758 // find the strongly connected components of the graph
2759 multitable<int_t> compVertices, compEnds;
2760 bool copyweights = !!transposed;
2761 int_t countSCC = SCC (*this, compVertices, compEnds,
2762 static_cast<diGraph<wType> *> (0), transposed, copyweights);
2763 if (countSCC <= 0)
2764 return 0;
2765
2766 // compute the maximum size of each strongly connected component
2767 int_t maxCompSize = compEnds [0];
2768 for (int_t comp = 1; comp < countSCC; ++ comp)
2769 {
2770 int_t compSize = compEnds [comp] - compEnds [comp - 1];
2771 if (maxCompSize < compSize)
2772 maxCompSize = compSize;
2773 }
2774
2775 // allocate arrays for weights and bit fields
2776 wType **FUpper = new wType * [maxCompSize + 1];
2777 wType **FLower = new wType * [maxCompSize + 1];
2778 BitField *finite = new BitField [maxCompSize + 1];
2779 for (int_t i = 0; i <= maxCompSize; ++ i)
2780 {
2781 FUpper [i] = new wType [maxCompSize];
2782 FLower [i] = new wType [maxCompSize];
2783 finite [i]. allocate (maxCompSize);
2784 }
2785
2786 // compute the numbers of vertices in each component
2787 int_t *numbers = new int_t [nVertices];
2788 int_t *components = new int_t [nVertices];
2789 for (int_t i = 0; i < nVertices; ++ i)
2790 components [i] = -1;
2791 int_t offset = 0;
2792 for (int_t comp = 0; comp < countSCC; ++ comp)
2793 {
2794 int_t maxOffset = compEnds [comp];
2795 int_t pos = offset;
2796 for (; pos < maxOffset; ++ pos)
2797 {
2798 numbers [compVertices [pos]] = pos - offset;
2799 components [compVertices [pos]] = comp;
2800 }
2801 offset = pos;
2802 }
2803
2804 // compute the minimum mean cycle weight for each component
2805 wType minWeight (0);
2806 for (int_t comp = 0; comp < countSCC; ++ comp)
2807 {
2808 int_t offset = comp ? compEnds [comp - 1] :
2809 static_cast<int_t> (0);
2810 int_t compSize = compEnds [comp] - offset;
2811 for (int_t i = 0; i <= compSize; ++ i)
2812 finite [i]. clearall (compSize);
2813 FUpper [0] [0] = 0;
2814 FLower [0] [0] = 0;
2815 finite [0]. set (0);
2816 // compute path progressions of given length
2817 for (int_t len = 1; len <= compSize; ++ len)
2818 {
2819 // process source vertices
2820 for (int_t i = 0; i < compSize; ++ i)
2821 {
2822 if (!finite [len - 1]. test (i))
2823 continue;
2824 wType prevUpper = FUpper [len - 1] [i];
2825 wType prevLower = FLower [len - 1] [i];
2826 int_t source = compVertices [offset + i];
2827
2828 // process target vertices (and edges)
2829 int_t edgeOffset = source ?
2830 edgeEnds [source - 1] :
2831 static_cast<int_t> (0);
2832 int_t edgeEnd = edgeEnds [source];
2833 for (; edgeOffset < edgeEnd; ++ edgeOffset)
2834 {
2835 int_t target = edges [edgeOffset];
2836 if (components [target] != comp)
2837 continue;
2838 int_t j = numbers [target];
2839 wType newUpper = rounding. add_up
2840 (prevUpper,
2841 weights [edgeOffset]);
2842 wType newLower = rounding. add_down
2843 (prevLower,
2844 weights [edgeOffset]);
2845 if (!finite [len]. test (j))
2846 {
2847 finite [len]. set (j);
2848 FUpper [len] [j] = newUpper;
2849 FLower [len] [j] = newLower;
2850 }
2851 else
2852 {
2853 wType &curUpper =
2854 FUpper [len] [j];
2855 if (newUpper < curUpper)
2856 curUpper = newUpper;
2857 wType &curLower =
2858 FLower [len] [j];
2859 if (newLower < curLower)
2860 curLower = newLower;
2861 }
2862 }
2863 }
2864 }
2865
2866 // compute the minimum mean cycle weight for this component
2867 wType minCompWeight (0);
2868 bool firstMin = true;
2869 for (int_t vert = 0; vert < compSize; ++ vert)
2870 {
2871 if (!finite [compSize]. test (vert))
2872 continue;
2873 bool firstAverage = true;
2874 wType maxAverage = 0;
2875 for (int_t first = 0; first < compSize; ++ first)
2876 {
2877 if (!finite [first]. test (vert))
2878 continue;
2879 const wType diff = rounding. sub_down
2880 (FLower [compSize] [vert],
2881 FUpper [first] [vert]);
2882 wType average = rounding. div_down
2883 (diff, compSize - first);
2884 if (firstAverage)
2885 {
2886 maxAverage = average;
2887 firstAverage = false;
2888 }
2889 else if (maxAverage < average)
2890 maxAverage = average;
2891 }
2892 if (firstMin || (maxAverage < minCompWeight))
2893 {
2894 if (firstAverage)
2895 throw "Bug in Karp's algorithm";
2896 minCompWeight = maxAverage;
2897 firstMin = false;
2898 }
2899 }
2900
2901 // make a correction to the total minimum if necessary
2902 if (!comp || (minCompWeight < minWeight))
2903 minWeight = minCompWeight;
2904 }
2905
2906 // release allocated memory
2907 delete [] components;
2908 delete [] numbers;
2909 for (int_t i = 0; i <= maxCompSize; ++ i)
2910 {
2911 finite [i]. free ();
2912 delete [] (FUpper [i]);
2913 delete [] (FLower [i]);
2914 }
2915 delete [] finite;
2916 delete [] FUpper;
2917 delete [] FLower;
2918
2919 // return the computed minimum
2920 return minWeight;
2921} /* diGraph::minMeanCycleWeight */
2922
2923template <class wType>
2924template <class roundType, class predType>
2925wType diGraph<wType>::minMeanCycleWeightMem (const roundType &rounding,
2926 diGraph<wType> *transposed, predType &predecessors) const
2927{
2928// NOTE: Support for CHECK_ROUNDING_WIDTH is currently in preparation.
2929
2930 // find the strongly connected components of the graph
2931 multitable<int_t> compVertices, compEnds;
2932 bool copyweights = !!transposed;
2933 int_t countSCC = SCC (*this, compVertices, compEnds,
2934 static_cast<diGraph<wType> *> (0), transposed, copyweights);
2935 if (countSCC <= 0)
2936 return 0;
2937
2938 // compute the maximum size of each strongly connected component
2939 int_t maxCompSize = compEnds [0];
2940 for (int_t comp = 1; comp < countSCC; ++ comp)
2941 {
2942 int_t compSize = compEnds [comp] - compEnds [comp - 1];
2943 if (maxCompSize < compSize)
2944 maxCompSize = compSize;
2945 }
2946
2947 // allocate arrays for weights and bit fields;
2948 // table 0 for F [0], tables 1 and 2 for F [k - 1] and F [k],
2949 // table 3 for F [n], table 4 for max of the quotients
2950 const int nTables (5);
2951 wType **FUpper = new wType * [nTables];
2952 wType **FLower = new wType * [nTables];
2953#ifdef CHECK_ROUNDING_WIDTH
2954 wType **FUpperE = new wType * [nTables];
2955 wType **FLowerE = new wType * [nTables];
2956#endif
2957 BitField *finite = new BitField [nTables];
2958 int_t *maxLength = new int_t [maxCompSize];
2959 for (int_t i = 0; i < nTables; ++ i)
2960 {
2961 FUpper [i] = new wType [maxCompSize];
2962 FLower [i] = new wType [maxCompSize];
2963#ifdef CHECK_ROUNDING_WIDTH
2964 FUpperE [i] = new wType [maxCompSize];
2965 FLowerE [i] = new wType [maxCompSize];
2966#endif
2967 finite [i]. allocate (maxCompSize);
2968 }
2969
2970 // compute the numbers of vertices in each component
2971 int_t *numbers = new int_t [nVertices];
2972 int_t *components = new int_t [nVertices];
2973 for (int_t i = 0; i < nVertices; ++ i)
2974 components [i] = -1;
2975 int_t offset = 0;
2976 for (int_t comp = 0; comp < countSCC; ++ comp)
2977 {
2978 int_t maxOffset = compEnds [comp];
2979 int_t pos = offset;
2980 for (; pos < maxOffset; ++ pos)
2981 {
2982 numbers [compVertices [pos]] = pos - offset;
2983 components [compVertices [pos]] = comp;
2984 }
2985 offset = pos;
2986 }
2987
2988 // compute the minimum mean cycle weight for each component
2989 wType minWeight (0);
2990#ifdef CHECK_ROUNDING_WIDTH
2991 wType minWeightE (0);
2992#endif
2993 // and remember the minimizing vertex in the formula for min max ...
2994 // as well as the size of that component
2995 int_t minVert (0);
2996 int_t minCompsize (0);
2997 for (int_t comp = 0; comp < countSCC; ++ comp)
2998 {
2999 int_t offset = comp ? compEnds [comp - 1] :
3000 static_cast<int_t> (0);
3001 int_t compSize = compEnds [comp] - offset;
3002 finite [0]. clearall (compSize);
3003 finite [4]. clearall (compSize);
3004 for (int_t i = 0; i < compSize; ++ i)
3005 maxLength [i] = -1;
3006 FUpper [0] [0] = 0;
3007 FLower [0] [0] = 0;
3008#ifdef CHECK_ROUNDING_WIDTH
3009 FUpperE [0] [0] = 0;
3010 FLowerE [0] [0] = 0;
3011#endif
3012 finite [0]. set (0);
3013
3014 // Pass 1: compute path progressions of maximal length
3015 const int_t maxLength1 (compSize + 1);
3016 for (int_t len = 1; len < maxLength1; ++ len)
3017 {
3018 // determine tables to use and clear the current one
3019 int_t prevIndex ((len == 1) ?
3020 0 : (((len - 1) & 1) + 1));
3021 int_t curIndex ((len == compSize) ?
3022 3 : ((len & 1) + 1));
3023 finite [curIndex]. clearall (compSize);
3024
3025 // process all the edges starting at vertices
3026 // to which finite paths are already known
3027 for (int_t i = finite [prevIndex].
3028 find (0, compSize);
3029 (i >= 0) && (i < compSize);
3030 i = finite [prevIndex]. find
3031 (i + 1, compSize))
3032 // for (int_t i = 0; i < compSize; ++ i)
3033 {
3034 // if (!finite [prevIndex]. test (i))
3035 // throw "Programming bug: infinite.";
3036 int_t source = compVertices [offset + i];
3037
3038 // process target vertices (and edges)
3039 int_t edgeEnd = edgeEnds [source];
3040 for (int_t edgeOffset = source ?
3041 edgeEnds [source - 1] :
3042 static_cast<int_t> (0);
3043 edgeOffset < edgeEnd; ++ edgeOffset)
3044 {
3045 int_t target = edges [edgeOffset];
3046 if (components [target] != comp)
3047 continue;
3048 int_t j = numbers [target];
3049 wType newLower = rounding. add_down
3050 (FLower [prevIndex] [i],
3051 weights [edgeOffset]);
3052#ifdef CHECK_ROUNDING_WIDTH
3053 wType newLowerE = rounding. add_up
3054 (FLowerE [prevIndex] [i],
3055 weights [edgeOffset]);
3056#endif
3057
3058 // if this is the first time that
3059 // a path of this length
3060 // to the vertex was encountered
3061 if (!finite [curIndex]. test (j))
3062 {
3063 finite [curIndex]. set (j);
3064 FLower [curIndex] [j] =
3065 newLower;
3066#ifdef CHECK_ROUNDING_WIDTH
3067 FLowerE [curIndex] [j] =
3068 newLowerE;
3069#endif
3070 predecessors. add (target,
3071 source, len);
3072 maxLength [j] = len;
3073 }
3074 // if a better path of this length
3075 // to the vertex was found
3076 else if (newLower <
3077 FLower [curIndex] [j])
3078 {
3079 FLower [curIndex] [j] =
3080 newLower;
3081#ifdef CHECK_ROUNDING_WIDTH
3082 FLowerE [curIndex] [j] =
3083 newLowerE;
3084#endif
3085 predecessors. add (target,
3086 source, len);
3087 maxLength [j] = len;
3088 }
3089 }
3090 }
3091 }
3092
3093 // set up the mean average at level 0
3094 finite [4]. set (0);
3095 FLower [4] [0] = rounding. div_down (FLower [3] [0],
3096 compSize);
3097#ifdef CHECK_ROUNDING_WIDTH
3098 FLowerE [4] [0] = rounding. div_up (FLowerE [3] [0],
3099 compSize);
3100#endif
3101
3102 // Pass 2: compute path progressions of all the lengths and
3103 // update the max values of the quotients for each vertex
3104 const int_t maxLength2 (compSize);
3105 for (int_t len = 1; len < maxLength2; ++ len)
3106 {
3107 // determine tables to use and clear the current one
3108 int_t prevIndex ((len == 1) ?
3109 0 : (((len - 1) & 1) + 1));
3110 int_t curIndex ((len & 1) + 1);
3111 finite [curIndex]. clearall (compSize);
3112
3113 // process all the edges starting at vertices
3114 // to which finite paths are already known
3115 for (int_t i = finite [prevIndex].
3116 find (0, compSize);
3117 (i >= 0) && (i < compSize);
3118 i = finite [prevIndex]. find
3119 (i + 1, compSize))
3120 // for (int_t i = 0; i < compSize; ++ i)
3121 {
3122 // if (!finite [prevIndex]. test (i))
3123 // throw "Programming bug: infinite.";
3124 int_t source = compVertices [offset + i];
3125
3126 // process target vertices (and edges)
3127 int_t edgeEnd = edgeEnds [source];
3128 for (int_t edgeOffset = source ?
3129 edgeEnds [source - 1] :
3130 static_cast<int_t> (0);
3131 edgeOffset < edgeEnd; ++ edgeOffset)
3132 {
3133 int_t target = edges [edgeOffset];
3134 if (components [target] != comp)
3135 continue;
3136 int_t j = numbers [target];
3137 wType newUpper = rounding. add_up
3138 (FUpper [prevIndex] [i],
3139 weights [edgeOffset]);
3140#ifdef CHECK_ROUNDING_WIDTH
3141 wType newUpperE = rounding. add_down
3142 (FUpperE [prevIndex] [i],
3143 weights [edgeOffset]);
3144#endif
3145 // if this is the first time that
3146 // a path of this length
3147 // to the vertex was encountered
3148 if (!finite [curIndex]. test (j))
3149 {
3150 finite [curIndex]. set (j);
3151 FUpper [curIndex] [j] =
3152 newUpper;
3153#ifdef CHECK_ROUNDING_WIDTH
3154 FUpperE [curIndex] [j] =
3155 newUpperE;
3156#endif
3157 }
3158 // if a better path of this length
3159 // to the vertex was found
3160 else if (newUpper <
3161 FUpper [curIndex] [j])
3162 {
3163 FUpper [curIndex] [j] =
3164 newUpper;
3165#ifdef CHECK_ROUNDING_WIDTH
3166 FUpperE [curIndex] [j] =
3167 newUpperE;
3168#endif
3169 }
3170 // otherwise, it is not necessary
3171 // to update the max average weight
3172 else
3173 {
3174 continue;
3175 }
3176
3177 // update the max average weight
3178 if (!finite [3]. test (j))
3179 continue;
3180 const wType diff = rounding. sub_down
3181 (FLower [3] [j],
3182 FUpper [curIndex] [j]);
3183#ifdef CHECK_ROUNDING_WIDTH
3184 const wType diffE = rounding. sub_up
3185 (FLowerE [3] [j],
3186 FUpperE [curIndex] [j]);
3187#endif
3188 const wType average = rounding.
3189 div_down (diff,
3190 compSize - len);
3191#ifdef CHECK_ROUNDING_WIDTH
3192 const wType averageE = rounding.
3193 div_up (diffE,
3194 compSize - len);
3195#endif
3196 if (!finite [4]. test (j))
3197 {
3198 finite [4]. set (j);
3199 FLower [4] [j] = average;
3200#ifdef CHECK_ROUNDING_WIDTH
3201 FLowerE [4] [j] = averageE;
3202#endif
3203 }
3204 else if (FLower [4] [j] < average)
3205 {
3206 FLower [4] [j] = average;
3207#ifdef CHECK_ROUNDING_WIDTH
3208 FLowerE [4] [j] = averageE;
3209#endif
3210 }
3211 }
3212 }
3213 }
3214
3215 // compute the minimum mean cycle weight for this component
3216 wType minCompWeight (0);
3217#ifdef CHECK_ROUNDING_WIDTH
3218 wType minCompWeightE (0);
3219#endif
3220 // and remember the minimizing vertex for the component
3221 int_t minCompVert (0);
3222 int_t maxCompLength (0);
3223 for (int_t vert = 0; vert < compSize; ++ vert)
3224 {
3225 if (!finite [4]. test (vert))
3226 continue;
3227 if (!vert || (FLower [4] [vert] < minCompWeight))
3228 {
3229 minCompWeight = FLower [4] [vert];
3230#ifdef CHECK_ROUNDING_WIDTH
3231 minCompWeightE = FLowerE [4] [vert];
3232#endif
3233 minCompVert = compVertices [offset + vert];
3234 maxCompLength = maxLength [vert];
3235 }
3236 }
3237
3238 // make a correction to the total minimum if necessary
3239 if (!comp || (minCompWeight < minWeight))
3240 {
3241 minWeight = minCompWeight;
3242#ifdef CHECK_ROUNDING_WIDTH
3243 minWeightE = minCompWeightE;
3244#endif
3245 minVert = minCompVert;
3246 minCompsize = maxCompLength;
3247 }
3248 }
3249
3250 // mark the minimizing vertex in the predecessors structure
3251 predecessors. add (minVert, minVert, -minCompsize);
3252
3253 // release allocated memory
3254 delete [] components;
3255 delete [] numbers;
3256 for (int_t i = 0; i < nTables; ++ i)
3257 {
3258 finite [i]. free ();
3259 delete [] (FUpper [i]);
3260 delete [] (FLower [i]);
3261#ifdef CHECK_ROUNDING_WIDTH
3262 delete [] (FUpperE [i]);
3263 delete [] (FLowerE [i]);
3264#endif
3265 }
3266 delete [] finite;
3267 delete [] maxLength;
3268 delete [] FUpper;
3269 delete [] FLower;
3270#ifdef CHECK_ROUNDING_WIDTH
3271 delete [] FUpperE;
3272 delete [] FLowerE;
3273#endif
3274
3275#ifdef CHECK_ROUNDING_WIDTH
3276 // show the loss of precision caused by rounding
3277 chomp::homology::sbug << "\nLoss of precision info: [" <<
3278 minWeight << ", " << minWeightE <<
3279 "], width: " << (minWeightE - minWeight) << ".\n";
3280#endif
3281
3282 // return the computed minimum
3283 return minWeight;
3284} /* diGraph::minMeanCycleWeightMem */
3285
3288{
3289// void add (int_t vertex, int_t predecessor, int_t stage);
3290 void add (int_t, int_t, int_t) {return;}
3291}; /* struct PredecessorsIgnore */
3292
3295{
3296public:
3299
3305 void add (int_t vertex, int_t predecessor, int_t stage);
3306
3309 template <class VectorType>
3310 void getCycle (VectorType &cycle) const;
3311
3312protected:
3317
3320
3323
3324}; /* class PredecessorsCycle */
3325
3327 searchStart (-1), compSize (0)
3328{
3329 return;
3330} /* PredecessorsCycle::PredecessorsCycle */
3331
3332inline void PredecessorsCycle::add (int_t vertex, int_t predecessor,
3333 int_t stage)
3334{
3335 if (stage >= 0)
3336 {
3337 pred [stage] [vertex] = predecessor;
3338 }
3339 else
3340 {
3341 searchStart = vertex;
3342 compSize = -stage;
3343 }
3344 return;
3345} /* PredecessorsCycle::add */
3346
3347template <class VectorType>
3348inline void PredecessorsCycle::getCycle (VectorType &cycle) const
3349{
3350 // return no cycle if no information is available
3351 if ((searchStart < 0) || (compSize <= 0))
3352 return;
3353
3354 // search for a cycle and return the first cycle found;
3355 // not a very efficient way: just store the path in a vector
3356 // and check if the newly added vertes is already there
3357 int_t current (searchStart);
3358 std::vector<int_t> path;
3359 for (int_t stage = compSize; stage >= 0; -- stage)
3360 {
3361 for (size_t n = 0; n < path. size (); ++ n)
3362 {
3363 if (path [n] == current)
3364 {
3365 for (size_t m = path. size ();
3366 m > n; -- m)
3367 {
3368 cycle. push_back (path [m - 1]);
3369 }
3370 return;
3371 }
3372 }
3373 path. push_back (current);
3374 current = pred [stage] [current];
3375 }
3376 return;
3377} /* PredecessorsCycle::getCycle */
3378
3379template <class wType>
3380template <class roundType>
3381inline wType diGraph<wType>::minMeanCycleWeightMem (const roundType &rounding,
3382 diGraph<wType> *transposed) const
3383{
3384 PredecessorsIgnore predecessorsIgnore;
3385 return this -> minMeanCycleWeightMem (rounding, transposed,
3386 predecessorsIgnore);
3387} /* diGraph::minMeanCycleWeightMem */
3388
3389template <class wType>
3390template <class arrayType, class roundType>
3391wType diGraph<wType>::minMeanPathWeight (const roundType &rounding,
3392 const arrayType &starting, int_t n) const
3393{
3394 // allocate arrays for weights and bit fields
3395 const int nIndices = 2;
3396 wType **F = new wType * [nIndices];
3397 BitField *finite = new BitField [nIndices];
3398 for (int i = 0; i < nIndices; ++ i)
3399 {
3400 F [i] = new wType [nVertices];
3401 finite [i]. allocate (nVertices);
3402 }
3403
3404 // set the zero path lengths from the initial vertices
3405 for (int_t i = 0; i < n; ++ i)
3406 {
3407 int_t v = starting [i];
3408 if ((v < 0) || (v >= nVertices))
3409 throw "Starting vertex out of range.";
3410 F [0] [v] = 0;
3411 finite [0]. set (v);
3412 }
3413
3414 // compute path progressions of given length and average weights
3415 wType minWeight (0);
3416 bool firstWeight = true;
3417 int_t maxLength (nVertices + 1);
3418 for (int_t len = 1; len < maxLength; ++ len)
3419 {
3420 // determine the indices for previous and current paths
3421 int_t prevIndex = (len - 1) & 1;
3422 int_t curIndex = len & 1;
3423 finite [curIndex]. clearall (nVertices);
3424
3425 // process source vertices
3426 for (int_t source = 0; source < nVertices; ++ source)
3427 {
3428 if (!finite [prevIndex]. test (source))
3429 continue;
3430 wType prevWeight = F [prevIndex] [source];
3431
3432 // process target vertices (and edges)
3433 int_t edgeOffset = source ?
3434 edgeEnds [source - 1] :
3435 static_cast<int_t> (0);
3436 int_t edgeEnd = edgeEnds [source];
3437 for (; edgeOffset < edgeEnd; ++ edgeOffset)
3438 {
3439 int_t target = edges [edgeOffset];
3440 wType newWeight = rounding. add_down
3441 (prevWeight, weights [edgeOffset]);
3442 if (!finite [curIndex]. test (target))
3443 {
3444 finite [curIndex]. set (target);
3445 F [curIndex] [target] = newWeight;
3446 }
3447 else if (newWeight < F [curIndex] [target])
3448 F [curIndex] [target] = newWeight;
3449 }
3450 }
3451
3452 // update the minimum mean path weight
3453 for (int_t vert = 0; vert < nVertices; ++ vert)
3454 {
3455 if (!finite [curIndex]. test (vert))
3456 continue;
3457 wType average = rounding. div_down
3458 (F [curIndex] [vert], len);
3459 if (firstWeight)
3460 {
3461 minWeight = average;
3462 firstWeight = false;
3463 }
3464 else if (average < minWeight)
3465 minWeight = average;
3466 }
3467 }
3468
3469 // release allocated memory
3470 for (int i = 0; i < nIndices; ++ i)
3471 {
3472 finite [i]. free ();
3473 delete [] (F [i]);
3474 }
3475 delete [] finite;
3476 delete [] F;
3477
3478 // return the computed minimum
3479 return minWeight;
3480} /* diGraph::minMeanPathWeight */
3481
3482template <class wType>
3483template <class arrayType>
3484wType diGraph<wType>::minMeanPathWeight (const arrayType &starting, int_t n)
3485 const
3486{
3487 const dummyRounding<wType> rounding = dummyRounding<wType> ();
3488 return minMeanPathWeight (rounding, starting, n);
3489} /* diGraph::minMeanPathWeight */
3490
3491
3492// --------------------------------------------------
3493// ------------- OTHER GRAPH ALGORITHMS -------------
3494// --------------------------------------------------
3495
3497template <class wType>
3498inline int_t addRenumEdges (const diGraph<wType> &g, int_t vertex,
3499 const int_t *newNum, int_t cur, int_t *srcVert,
3500 diGraph<wType> &result)
3501{
3502 int_t nEdges = g. countEdges (vertex);
3503 // add all the edges that start at the component
3504 for (int_t edge = 0; edge < nEdges; ++ edge)
3505 {
3506 // determine the dest. vertex of the edge
3507 int_t dest = newNum [g. getEdge (vertex, edge)];
3508 // if this is an edge to self, then ignore it
3509 if (dest == cur)
3510 continue;
3511 // if the edge has already been added,
3512 // then skip it
3513 if (srcVert [dest] == cur)
3514 continue;
3515 // remember that the dest. vertex has an edge
3516 // pointing out from the current vertex
3517 srcVert [dest] = cur;
3518 // add the edge to the result graph
3519 result. addEdge (dest);
3520 }
3521 return 0;
3522} /* addRenumEdges */
3523
3529template <class wType, class Table1, class Table2>
3531 int_t compNum, Table1 &compVertices, Table2 &compEnds,
3532 diGraph<wType> &result, int_t *newNumbers = 0)
3533{
3534 // do nothing if the input graph is empty
3535 int_t nVert = g. countVertices ();
3536 if (!nVert)
3537 return 0;
3538
3539 // compute the new numbers of vertices: newNum [i] is the
3540 // number of vertex 'i' from 'g' in the resulting graph
3541 int_t *newNum = newNumbers ? newNumbers : new int_t [nVert];
3542 for (int_t i = 0; i < nVert; ++ i)
3543 newNum [i] = -1;
3544 int_t cur = 0; // current vertex number in the new graph
3545 int_t pos = 0; // position in compVertices
3546 while (cur < compNum)
3547 {
3548 int_t posEnd = compEnds [cur];
3549 while (pos < posEnd)
3550 newNum [compVertices [pos ++]] = cur;
3551 ++ cur;
3552 }
3553 for (int_t i = 0; i < nVert; ++ i)
3554 {
3555 if (newNum [i] < 0)
3556 newNum [i] = cur ++;
3557 }
3558
3559 // prepare a table to mark the most recent source vertex for edges:
3560 // srcVert [j] contains i if the edge i -> j has just been added
3561 int_t newVert = nVert - (compNum ? compEnds [compNum - 1] :
3562 static_cast<int_t> (0)) + compNum;
3563 // debug:
3564 if (cur != newVert)
3565 throw "DEBUG: Wrong numbers.";
3566 int_t *srcVert = new int_t [newVert];
3567 for (int_t i = 0; i < newVert; ++ i)
3568 srcVert [i] = -1;
3569
3570 // scan the input graph and create the resulting graph: begin with
3571 // the vertices in the collapsed groups
3572 cur = 0, pos = 0;
3573 while (cur < compNum)
3574 {
3575 // add a new vertex to the result graph
3576 result. addVertex ();
3577 // for all the vertices in this component...
3578 int_t posEnd = compEnds [cur];
3579 while (pos < posEnd)
3580 {
3581 // take the next vertex from the component
3582 int_t vertex = compVertices [pos ++];
3583 // add the appropriate edges to the result graph
3584 addRenumEdges (g, vertex, newNum, cur,
3585 srcVert, result);
3586 }
3587 ++ cur;
3588 }
3589 // process the remaining vertices of the graph
3590 for (int_t vertex = 0; vertex < nVert; ++ vertex)
3591 {
3592 // debug
3593 if (newNum [vertex] > cur)
3594 throw "DEBUG: Wrong order.";
3595 // if the vertex has already been processed, skip it
3596 if (newNum [vertex] != cur)
3597 continue;
3598 // add the appropriate edges to the result graph
3599 result. addVertex ();
3600 addRenumEdges (g, vertex, newNum, cur, srcVert, result);
3601 ++ cur;
3602 }
3603
3604 // free memory and exit
3605 delete [] srcVert;
3606 if (!newNumbers)
3607 delete [] newNum;
3608 return 0;
3609} /* collapseVertices */
3610
3612template <class wType, class TabSets>
3613inline int_t addRenumEdges2 (const diGraph<wType> &g, int_t vertex,
3614 const int_t *newNum, TabSets &numSets,
3615 int_t cur, int_t *srcVert, diGraph<wType> &result)
3616{
3617 int_t nEdges = g. countEdges (vertex);
3618
3619 // add all the edges that start at this vertex
3620 for (int_t edge = 0; edge < nEdges; ++ edge)
3621 {
3622 // determine the dest. vertex of the edge
3623 int_t destNumber = newNum [g. getEdge (vertex, edge)];
3624
3625 // consider all the destination vertices
3626 int_t destSize = (destNumber < 0) ?
3627 numSets [-destNumber]. size () :
3628 static_cast<int_t> (1);
3629 for (int_t i = 0; i < destSize; ++ i)
3630 {
3631 // determine the consecutive destination vertex
3632 int_t dest = (destNumber < 0) ?
3633 numSets [-destNumber] [i] : destNumber;
3634
3635 // if this is an edge to self, then ignore it
3636 if (dest == cur)
3637 continue;
3638
3639 // if the edge has already been added,
3640 // then skip it
3641 if (srcVert [dest] == cur)
3642 continue;
3643
3644 // add the edge to the result graph
3645 result. addEdge (dest);
3646 }
3647 }
3648 return 0;
3649} /* addRenumEdges2 */
3650
3655template <class wType, class Table1, class Table2>
3657 int_t compNum, Table1 &compVertices, Table2 &compEnds,
3658 diGraph<wType> &result)
3659{
3660 // do nothing if the input graph is empty
3661 int_t nVert = g. countVertices ();
3662 if (!nVert)
3663 return 0;
3664
3665 // compute the new numbers of vertices: newNum [i] is the
3666 // number of vertex 'i' from 'g' in the resulting graph,
3667 // unless negative; then it points to a set of numbers,
3668 // with -1 meaning "not defined, yet"
3669 int_t *newNum = new int_t [nVert];
3670 for (int_t i = 0; i < nVert; ++ i)
3671 newNum [i] = -1;
3672
3673 // sets of numbers of vertices; the numbers refering to the sets
3674 // begin with 2, thus the first two sets are skipped
3676 // the number of the set waiting to be used next
3677 int_t numSetCur = 2;
3678
3679 int_t cur = 0; // current vertex number in the new graph
3680 int_t pos = 0; // position in compVertices
3681 while (cur < compNum)
3682 {
3683 int_t posEnd = compEnds [cur];
3684 while (pos < posEnd)
3685 {
3686 int_t number = compVertices [pos ++];
3687 if (newNum [number] == -1)
3688 newNum [number] = cur;
3689 else if (newNum [number] < 0)
3690 numSets [-newNum [number]]. add (cur);
3691 else
3692 {
3693 numSets [numSetCur]. add (newNum [number]);
3694 numSets [numSetCur]. add (cur);
3695 newNum [number] = -(numSetCur ++);
3696 }
3697 }
3698 ++ cur;
3699 }
3700 for (int_t i = 0; i < nVert; ++ i)
3701 {
3702 if (newNum [i] == -1)
3703 newNum [i] = cur ++;
3704 }
3705
3706 // prepare a table to mark the most recent source vertex for edges:
3707 // srcVert [j] contains i if the edge i -> j has just been added
3708 int_t newVert = cur;
3709 int_t *srcVert = new int_t [newVert];
3710 for (int_t i = 0; i < newVert; ++ i)
3711 srcVert [i] = -1;
3712
3713 // scan the input graph and create the resulting graph: begin with
3714 // the vertices in the collapsed groups
3715 cur = 0;
3716 pos = 0;
3717 while (cur < compNum)
3718 {
3719 // add a new vertex to the result graph
3720 result. addVertex ();
3721
3722 // for all the vertices in this component...
3723 int_t posEnd = compEnds [cur];
3724 while (pos < posEnd)
3725 {
3726 // take the next vertex from the component
3727 int_t vertex = compVertices [pos ++];
3728
3729 // add the appropriate edges to the result graph
3730 addRenumEdges2 (g, vertex, newNum, numSets, cur,
3731 srcVert, result);
3732 }
3733 ++ cur;
3734 }
3735
3736 // process the remaining vertices of the graph
3737 for (int_t vertex = 0; vertex < nVert; ++ vertex)
3738 {
3739 // debug
3740 if (newNum [vertex] > cur)
3741 throw "DEBUG: Wrong order 2.";
3742
3743 // if the vertex has already been processed, skip it
3744 if (newNum [vertex] != cur)
3745 continue;
3746
3747 // add the appropriate edges to the result graph
3748 result. addVertex ();
3749 addRenumEdges2 (g, vertex, newNum, numSets, cur,
3750 srcVert, result);
3751 ++ cur;
3752 }
3753
3754 // free memory and exit
3755 delete [] srcVert;
3756 delete [] newNum;
3757 return 0;
3758} /* collapseVertices2 */
3759
3768template <class wType>
3770 diGraph<wType> &result)
3771{
3772 // remember the number of vertices in the input graph
3773 int_t nVertG = g. countVertices ();
3774 if (!nVertG)
3775 return 0;
3776
3777 // prepare a bitfield in which visited vertices will be marked
3778 BitField visited;
3779 visited. allocate (nVertG);
3780 visited. clearall (nVertG);
3781
3782 // run DFS for each of the starting vertices
3783 for (int_t startVertex = 0; startVertex < nVert; ++ startVertex)
3784 {
3785 // add this vertex to the resulting graph
3786 result. addVertex ();
3787
3788 // prepare a counter and a stack of visited vertices
3789 int_t nVisited = 0;
3790 std::stack<int_t> s_visited;
3791
3792 // prepare stacks for the DFS algorithm
3793 std::stack<int_t> s_vertex;
3794 std::stack<int_t> s_edge;
3795
3796 // mark the starting vertex as visited
3797 visited. set (startVertex);
3798 s_visited. push (startVertex);
3799 ++ nVisited;
3800
3801 // use DFS to visit vertices reachable from that vertex
3802 int_t vertex = startVertex;
3803 int_t edge = 0;
3804 while (1)
3805 {
3806 // go back with the recursion
3807 // if all the edges have been processed
3808 if (edge >= g. countEdges (vertex))
3809 {
3810 // if this was the top recursion level
3811 // then quit
3812 if (s_vertex. empty ())
3813 break;
3814
3815 // return from the recursion
3816 vertex = s_vertex. top ();
3817 s_vertex. pop ();
3818 edge = s_edge. top ();
3819 s_edge. pop ();
3820 continue;
3821 }
3822
3823 // take the next vertex
3824 int_t next = g. getEdge (vertex, edge ++);
3825
3826 // go to the deeper recursion level if not visited
3827 if (!visited. test (next))
3828 {
3829 // add an edge to the result if necessary
3830 if (next < nVert)
3831 result. addEdge (next);
3832
3833 // store the previous variables at the stacks
3834 s_vertex. push (vertex);
3835 s_edge. push (edge);
3836
3837 // take the new vertex
3838 vertex = next;
3839 edge = 0;
3840
3841 // mark the new vertex as visited
3842 visited. set (vertex);
3843 s_visited. push (vertex);
3844 ++ nVisited;
3845 }
3846 }
3847
3848 // if this was the last vertex then skip the rest
3849 if (startVertex == nVert - 1)
3850 break;
3851
3852 // mark each vertex as non-visited
3853 if (nVisited > (nVertG >> 6))
3854 {
3855 visited. clearall (nVertG);
3856 }
3857 else
3858 {
3859 while (!s_visited. empty ())
3860 {
3861 int_t vertex = s_visited. top ();
3862 s_visited. pop ();
3863 visited. clear (vertex);
3864 }
3865 }
3866 }
3867
3868 // free memory and exit
3869 visited. free ();
3870 return 0;
3871} /* connectionGraph */
3872
3878template <class GraphType>
3879inline int_t computePeriod (const GraphType &g)
3880{
3881 // remember the number of vertices in the input graph
3882 int_t nVertG = g. countVertices ();
3883 if (!nVertG)
3884 return 0;
3885
3886 // prepare an array to record the depth of each visited vertex
3887 std::vector<int_t> visited (nVertG, 0);
3888
3889 // run DFS starting at the first vertex
3890 // prepare stacks for the DFS algorithm
3891 std::stack<int_t> s_vertex;
3892 std::stack<int_t> s_edge;
3893
3894 // mark the starting vertex as visited
3895 visited [0] = 1;
3896
3897 // use DFS to visit vertices reachable from that vertex
3898 int_t vertex = 0;
3899 int_t edge = 0;
3900 int_t level = 1;
3901 int_t period = 0;
3902 while (1)
3903 {
3904 // go back with the recursion
3905 // if all the edges have been processed
3906 if (edge >= g. countEdges (vertex))
3907 {
3908 // if this was the top recursion level then quit
3909 if (s_vertex. empty ())
3910 break;
3911
3912 // return from the recursion
3913 vertex = s_vertex. top ();
3914 s_vertex. pop ();
3915 edge = s_edge. top ();
3916 s_edge. pop ();
3917 -- level;
3918 continue;
3919 }
3920
3921 // take the next vertex
3922 int_t next = g. getEdge (vertex, edge ++);
3923
3924 // update the GCD of the cycle lengths
3925 if (visited [next])
3926 {
3927 // determine the period provided by the cycle
3928 int_t newPeriod = visited [next] - level - 1;
3929 if (newPeriod < 0)
3930 newPeriod = -newPeriod;
3931
3932 // compute the GCD of the old and new periods
3933 int_t a = newPeriod;
3934 int_t b = period;
3935 while (b)
3936 {
3937 int_t t = b;
3938 b = a % b;
3939 a = t;
3940 }
3941 period = a;
3942
3943 // if the graph turns out to be aperiodic
3944 // then immediately return the result
3945 if (period == 1)
3946 return period;
3947 }
3948
3949 // go to the deeper recursion level if not visited
3950 else
3951 {
3952 // store the previous variables at the stacks
3953 s_vertex. push (vertex);
3954 s_edge. push (edge);
3955
3956 // take the new vertex
3957 vertex = next;
3958 edge = 0;
3959 ++ level;
3960
3961 // mark the new vertex as visited
3962 visited [vertex] = level;
3963 }
3964 }
3965
3966 // return the computed peirod and exit
3967 return period;
3968} /* computePeriod */
3969
3975template <class wType>
3977 diGraph<wType> &result)
3978{
3979 // remember the number of vertices in the input graph
3980 int_t nVertG = g. countVertices ();
3981 if (!nVertG)
3982 return 0;
3983
3984 // mark each vertex as non-visited
3985 BitField visited;
3986 visited. allocate (nVertG);
3987 visited. clearall (nVertG);
3988
3989 // create the sets of vertices reachable from each vertex
3990 BitSets lists (nVertG, nVert);
3991
3992 // prepare stacks for the DFS algorithm
3993 std::stack<int_t> s_vertex;
3994 std::stack<int_t> s_edge;
3995
3996 // use DFS to propagate the reachable sets
3997 int_t startVertex = 0;
3998 int_t vertex = 0;
3999 int_t edge = 0;
4000 visited. set (vertex);
4001 while (1)
4002 {
4003 // go back with the recursion
4004 // if all the edges have been processed
4005 if (edge >= g. countEdges (vertex))
4006 {
4007 // if this was the top recursion level,
4008 // then find another starting point or quit
4009 if (s_vertex. empty ())
4010 {
4011 while ((startVertex < nVertG) &&
4012 (visited. test (startVertex)))
4013 ++ startVertex;
4014 if (startVertex >= nVertG)
4015 break;
4016 vertex = startVertex;
4017 edge = 0;
4018 visited. set (vertex);
4019 continue;
4020 }
4021
4022 // determine the previous vertex (to trace back to)
4023 int_t prev = s_vertex. top ();
4024
4025 // add the list of the current vertex
4026 // to the list of the previous vertex
4027 // unless that was one of the first 'nVert' vertices
4028 if (vertex >= nVert)
4029 lists. addset (prev, vertex);
4030
4031 // return from the recursion
4032 vertex = prev;
4033 s_vertex. pop ();
4034 edge = s_edge. top ();
4035 s_edge. pop ();
4036 continue;
4037 }
4038
4039 // take the next vertex
4040 int_t next = g. getEdge (vertex, edge ++);
4041
4042 // add the number to the list if appropriate
4043 if (next < nVert)
4044 lists. add (vertex, next);
4045
4046 // go to the deeper recursion level if vertex not visited
4047 if (!visited. test (next))
4048 {
4049 // store the previous variables at the stacks
4050 s_vertex. push (vertex);
4051 s_edge. push (edge);
4052
4053 // take the new vertex and mark as visited
4054 vertex = next;
4055 edge = 0;
4056 visited. set (vertex);
4057 }
4058
4059 // add the list of the next vertex to the current one
4060 // if the vertex has already been visited before
4061 // and the vertex is not one of the first 'nVert' ones
4062 else if (next >= nVert)
4063 {
4064 lists. addset (vertex, next);
4065 }
4066 }
4067
4068 // create the result graph based on the lists of edges
4069 for (int_t vertex = 0; vertex < nVert; ++ vertex)
4070 {
4071 result. addVertex ();
4072 int_t edge = lists. get (vertex);
4073 while (edge >= 0)
4074 {
4075 result. addEdge (edge);
4076 edge = lists. get (vertex, edge + 1);
4077 }
4078 }
4079
4080 // free memory and exit
4081 visited. free ();
4082 return 0;
4083} /* inclusionGraph */
4084
4085// --------------------------------------------------
4086
4095template<class wType, class TConn>
4097 diGraph<wType> &result, TConn &connections)
4098{
4099 // remember the number of vertices in the input graph
4100 int_t nVertG = g. countVertices ();
4101 if (!nVertG)
4102 return 0;
4103
4104 // mark each vertex as non-visited
4105 BitField visited;
4106 visited. allocate (nVertG);
4107 visited. clearall (nVertG);
4108
4109 // create the sets of vertices reachable from each vertex
4110 BitSets forwardlists (nVertG, nVert);
4111
4112 // prepare stacks for the DFS algorithm
4113 std::stack<int_t> s_vertex;
4114 std::stack<int_t> s_edge;
4115
4116 // use DFS to propagate the reachable sets
4117 int_t startVertex = 0;
4118 int_t vertex = 0;
4119 int_t edge = 0;
4120 visited. set (vertex);
4121 while (1)
4122 {
4123 // go back with the recursion
4124 // if all the edges have been processed
4125 if (edge >= g. countEdges (vertex))
4126 {
4127 // if this was the top recursion level,
4128 // then find another starting point or quit
4129 if (s_vertex. empty ())
4130 {
4131 while ((startVertex < nVertG) &&
4132 (visited. test (startVertex)))
4133 ++ startVertex;
4134 if (startVertex >= nVertG)
4135 break;
4136 vertex = startVertex;
4137 edge = 0;
4138 visited. set (vertex);
4139 continue;
4140 }
4141
4142 // determine the previous vertex (to trace back to)
4143 int_t prev = s_vertex. top ();
4144
4145 // add the list of the current vertex
4146 // to the list of the previous vertex
4147 // unless that was one of the first 'nVert' vertices
4148 if (vertex >= nVert)
4149 forwardlists. addset (prev, vertex);
4150
4151 // return from the recursion
4152 vertex = prev;
4153 s_vertex. pop ();
4154 edge = s_edge. top ();
4155 s_edge. pop ();
4156 continue;
4157 }
4158
4159 // take the next vertex
4160 int_t next = g. getEdge (vertex, edge ++);
4161
4162 // add the number to the list if appropriate
4163 if (next < nVert)
4164 forwardlists. add (vertex, next);
4165
4166 // go to the deeper recursion level if vertex not visited
4167 if (!visited. test (next))
4168 {
4169 // store the previous variables at the stacks
4170 s_vertex. push (vertex);
4171 s_edge. push (edge);
4172
4173 // take the new vertex and mark as visited
4174 vertex = next;
4175 edge = 0;
4176 visited. set (vertex);
4177 }
4178
4179 // add the list of the next vertex to the current one
4180 // if the vertex has already been visited before
4181 // and the vertex is not one of the first 'nVert' ones
4182 else if (next >= nVert)
4183 {
4184 forwardlists. addset (vertex, next);
4185 }
4186 }
4187
4188 // ------------------------------------------
4189
4190 // create the sets of vertices that can reach each vertex
4191 BitSets backlists (nVertG, nVert);
4192
4193 diGraph<wType> gT;
4194 g. transpose (gT);
4195
4196 // do a simple test for debugging purposes
4197 if (!s_vertex. empty () || !s_edge. empty ())
4198 throw "DEBUG: Nonempty stacks in 'inclusionGraph'.";
4199
4200 // mark all the vertices as unvisited for the backward run
4201 visited. clearall (nVertG);
4202
4203 // use DFS to propagate the reachable sets
4204 startVertex = 0;
4205 vertex = 0;
4206 edge = 0;
4207 visited. set (vertex);
4208 while (1)
4209 {
4210 // go back with the recursion
4211 // if all the edges have been processed
4212 if (edge >= gT. countEdges (vertex))
4213 {
4214 // if this was the top recursion level,
4215 // then find another starting point or quit
4216 if (s_vertex. empty ())
4217 {
4218 while ((startVertex < nVertG) &&
4219 (visited. test (startVertex)))
4220 ++ startVertex;
4221 if (startVertex >= nVertG)
4222 break;
4223 vertex = startVertex;
4224 edge = 0;
4225 visited. set (vertex);
4226 continue;
4227 }
4228
4229 // determine the previous vertex (to trace back to)
4230 int_t prev = s_vertex. top ();
4231
4232 // add the list of the current vertex
4233 // to the list of the previous vertex
4234 // unless that was one of the first 'nVert' vertices
4235 if (vertex >= nVert)
4236 backlists. addset (prev, vertex);
4237
4238 // return from the recursion
4239 vertex = prev;
4240 s_vertex. pop ();
4241 edge = s_edge. top ();
4242 s_edge. pop ();
4243 continue;
4244 }
4245
4246 // take the next vertex
4247 int_t next = gT. getEdge (vertex, edge ++);
4248
4249 // add the number to the list if appropriate
4250 if (next < nVert)
4251 backlists. add (vertex, next);
4252
4253 // go to the deeper recursion level if vertex not visited
4254 if (!visited. test (next))
4255 {
4256 // store the previous variables at the stacks
4257 s_vertex. push (vertex);
4258 s_edge. push (edge);
4259
4260 // take the new vertex and mark as visited
4261 vertex = next;
4262 edge = 0;
4263 visited. set (vertex);
4264 }
4265
4266 // add the list of the next vertex to the current one
4267 // if the vertex has already been visited before
4268 // and the vertex is not one of the first 'nVert' ones
4269 else if (next >= nVert)
4270 {
4271 backlists. addset (vertex, next);
4272 }
4273 }
4274
4275 // ------------------------------------------
4276
4277 // record the connections to the obtained data structure
4278 for (int_t v = nVert; v < nVertG; ++ v)
4279 {
4280 int_t bvertex = backlists. get (v);
4281 while (bvertex >= 0)
4282 {
4283 int_t fvertex = forwardlists. get (v);
4284 while (fvertex >= 0)
4285 {
4286 connections (bvertex, fvertex, v);
4287 fvertex = forwardlists. get (v, fvertex + 1);
4288 }
4289 bvertex = backlists. get (v, bvertex + 1);
4290 }
4291 }
4292
4293 // ------------------------------------------
4294
4295 // create the result graph based on the lists of edges
4296 for (int_t vertex = 0; vertex < nVert; ++ vertex)
4297 {
4298 result. addVertex ();
4299 int_t edge = forwardlists. get (vertex);
4300 while (edge >= 0)
4301 {
4302 result. addEdge (edge);
4303 edge = forwardlists. get (vertex, edge + 1);
4304 }
4305 }
4306
4307 // free memory and exit
4308 visited. free ();
4309 return 0;
4310} /* inclusionGraph */
4311
4312// --------------------------------------------------
4313
4317template <class wType, class matrix>
4318inline void graph2matrix (const diGraph<wType> &g, matrix &m)
4319{
4320 int_t nVert = g. countVertices ();
4321 for (int_t v = 0; v < nVert; ++ v)
4322 {
4323 int_t nEdges = g. countEdges (v);
4324 for (int_t e = 0; e < nEdges; ++ e)
4325 {
4326 int_t w = g. getEdge (v, e);
4327 m [v] [w] = 1;
4328 }
4329 }
4330 return;
4331} /* graph2matrix */
4332
4337template <class wType, class matrix>
4338inline void matrix2graph (const matrix &m, int_t n, diGraph<wType> &g)
4339{
4340 for (int_t v = 0; v < n; ++ v)
4341 {
4342 g. addVertex ();
4343 for (int_t w = 0; w < n; ++ w)
4344 if (m [v] [w])
4345 g. addEdge (w);
4346 }
4347 return;
4348} /* matrix2graph */
4349
4350// --------------------------------------------------
4351
4355template <class matrix>
4356inline void transitiveClosure (matrix &m, int_t n)
4357{
4358 for (int_t k = 0; k < n; ++ k)
4359 {
4360 for (int_t i = 0; i < n; ++ i)
4361 {
4362 for (int_t j = 0; j < n; ++ j)
4363 {
4364 if (m [i] [k] && m [k] [j])
4365 m [i] [j] = 1;
4366 }
4367 }
4368 }
4369 return;
4370} /* transitiveClosure */
4371
4379template <class matrix>
4380inline void transitiveReduction (matrix &m, int_t n)
4381{
4382 for (int_t k = n - 1; k >= 0; -- k)
4383 {
4384 for (int_t i = 0; i < n; ++ i)
4385 {
4386 for (int_t j = 0; j < n; ++ j)
4387 {
4388 if (m [i] [k] && m [k] [j])
4389 m [i] [j] = 0;
4390 }
4391 }
4392 }
4393 return;
4394} /* transitiveReduction */
4395
4398template <class wType>
4400 diGraph<wType> &gRed)
4401{
4402 int_t nVert = g. countVertices ();
4403 if (nVert <= 0)
4404 return;
4405 flatMatrix<char> m (nVert);
4406 m. clear (0);
4407 graph2matrix (g, m);
4408 transitiveClosure (m, nVert);
4409 transitiveReduction (m, nVert);
4410 matrix2graph (m, nVert, gRed);
4411 return;
4412} /* transitiveReduction */
4413
4414
4415} // namespace homology
4416} // namespace chomp
4417
4418#endif // _CHOMP_STRUCT_DIGRAPH_H_
4419
4421
An auto_array template that mimics selected behaviors of the std::auto_ptr template,...
This file contains the definition of a bitfield class which works an array of bits.
This file defines a class that uses bit representation of a set to store many small sets.
This class defines a bit field that is part of some larger array or that uses an allocated piece of m...
Definition: bitfield.h:73
This class uses bit representation to store many small sets.
Definition: bitsets.h:58
This template contains the definition of a Fibonacci heap that can be used as an efficient priority q...
Definition: fibheap.h:63
A helper class for determining a cycle that realizes the minimum.
Definition: digraph.h:3295
void getCycle(VectorType &cycle) const
Fills in a vector with a cycle that realizes the minimum, using the push_back method to add the conse...
Definition: digraph.h:3348
PredecessorsCycle()
The default constructor.
Definition: digraph.h:3326
void add(int_t vertex, int_t predecessor, int_t stage)
Adds a predecessor information for the given vertex at the given stage (path progression length).
Definition: digraph.h:3332
chomp::homology::multitable< chomp::homology::multitable< int_t > > pred
The array of predecessors at each stage.
Definition: digraph.h:3316
int_t searchStart
The vertex number to start back-tracing the cycle from.
Definition: digraph.h:3319
int_t compSize
The size of the component with the cycle to search.
Definition: digraph.h:3322
An auto_array template that mimics selected behaviors of the std::auto_ptr template,...
Definition: autoarray.h:54
A class for representing a positive number with negative values serving as the infinity (used in the ...
Definition: digraph.h:515
const wType & getValue() const
Returns the value stored in this object.
Definition: digraph.h:548
bool isInfinity() const
Returns true iff the value corresponds to the infinity.
Definition: digraph.h:542
wType value
The actual number.
Definition: digraph.h:577
posWeight(const wType &_value)
An optional constructor.
Definition: digraph.h:525
posWeight()
The default constructor.
Definition: digraph.h:518
void setInfinity()
Sets the value to the infinity.
Definition: digraph.h:535
friend bool operator<(const posWeight &x, const posWeight &y)
The < operator for comparing the numbers.
Definition: digraph.h:554
friend std::ostream & operator<<(std::ostream &out, const posWeight &x)
The operator for showing the number to the output stream.
Definition: digraph.h:565
This class defines a directed graph with very limited number of operations, and a few specific algori...
Definition: digraph.h:143
const wType & getWeight(int_t vertex, int_t i) const
Retrieves the weight of the given edge.
Definition: digraph.h:799
void writeEdges(Table &tab) const
Fills out a table that represents all the edges of the graph.
Definition: digraph.h:825
void swap(diGraph< wType > &g)
Swaps the data with another graph.
Definition: digraph.h:631
bool DFSforestStack(Table1 &tab, Table1 &ntab, int_t vertex, int_t treeNumber, int_t countTrees, Table2 &compVertices, int_t &curVertex, diGraph *sccGraph, int_t *sccEdgeAdded) const
A stack version of the recurrent procedure for DFSforest.
Definition: digraph.h:1194
diGraph()
The default constructor of an empty graph.
Definition: digraph.h:585
int_t DFSforest(const Table1 &ordered, Table2 &compVertices, Table3 &compEnds, bool nontrivial=false, diGraph< wType > *sccGraph=0) const
Computes the DFS forest.
Definition: digraph.h:1294
wType minPathWeight(const roundType &rounding, bool ignoreNegLoop=false, int sparseGraph=-1) const
Uses the Floyd-Warshall algorithm or Johnson's algorithm, depending on the number of edges,...
Definition: digraph.h:2291
wType Edmonds() const
Runs the Edmonds algorithm to compute the shortest path that runs through all the vertices of the gra...
Definition: digraph.h:1809
multitable< int_t > edges
A table with edge target numbers.
Definition: digraph.h:463
bool DFSforestRecurrent(Table1 &tab, Table1 &ntab, int_t vertex, int_t treeNumber, int_t countTrees, Table2 &compVertices, int_t &curVertex, diGraph *sccGraph, int_t *sccEdgeAdded) const
The recurrent procedure for DFSforest.
Definition: digraph.h:1141
void addEdge(int_t target)
Adds an edge starting at the last vertex.
Definition: digraph.h:650
wType minMeanCycleWeightMem(const roundType &rounding, diGraph< wType > *transposed, predType &predecessors) const
A rigorous numerics version of Karp's algorithm modified in such a way that the memory usage is minim...
Definition: digraph.h:2925
outType & show(outType &out, bool showWeights=false) const
Outputs the graph to a text stream in a human-readable format.
Definition: digraph.h:2353
friend bool operator==(const diGraph< wType1 > &g1, const diGraph< wType2 > &g2)
Operator == for comparing digraphs.
Definition: digraph.h:600
wType minMeanCycleWeight(diGraph< wType > *transposed=0) const
Runs Karp's algorithm for each strongly connected component of the graph and returns the minimum mean...
Definition: digraph.h:2608
int_t nVertices
The number of vertices.
Definition: digraph.h:456
void subgraph(diGraph< wType1 > &result, const Table &tab, bool copyweights=false) const
Computes a restriction of the graph to its subgraph.
Definition: digraph.h:880
void Dijkstra(const roundType &rounding, int_t source, lenTable &len, weightsType &edgeWeights) const
Dijkstra's algorithm for solving the single-source shortest paths problem if all the edge weights are...
Definition: digraph.h:1577
wType minMeanPathWeight(const roundType &rounding, const arrayType &starting, int_t n) const
Runs an algorithm based on Karp's idea to compute the minimum mean path weight for paths starting at ...
Definition: digraph.h:3391
void removeVertex(void)
Removes the last vertex and all the edges going out from it.
Definition: digraph.h:714
wType FloydWarshall(const roundType &rounding, arrayType &arr, bool setInfinity=true, bool ignoreNegLoop=false) const
Runs the Floyd-Warshall algorithm to compute the shortest paths between all pairs of vertices in the ...
Definition: digraph.h:1963
void setWeights(const Table &tab)
Sets the weights of all the edges at a time.
Definition: digraph.h:703
int_t shortestPath(int_t source, int_t destination) const
Computes the length of the shortest nontrivial path from the given vertex to another one.
Definition: digraph.h:1490
wType weight_type
The type of the weight of edges.
Definition: digraph.h:146
multitable< int_t > edgeEnds
A table with the offsets of the one-after-the-last edge of each vertex.
Definition: digraph.h:460
~diGraph()
The destructor.
Definition: digraph.h:592
int_t countVertices(void) const
Returns the number of vertices.
Definition: digraph.h:766
int_t shortestLoop(int_t origin) const
Computes the length of the shortest loop from the given vertex to itself.
Definition: digraph.h:1570
void getWeights(Table &tab) const
Gets the weights of all the edges at a time.
Definition: digraph.h:814
void DFScolor(Table &tab, const Color &color, int_t vertex=0) const
Marks each vertex visited by DFS with the given color, starting with the given vertex.
Definition: digraph.h:1001
void DFSfinishTime(Table &tab) const
Computes the DFS finishing time for each vertex.
Definition: digraph.h:1099
void DFSfinishTimeStack(Table &tab, int_t vertex, int_t &counter) const
A stack version of the recurrent procedure for DFSfinishTime.
Definition: digraph.h:1033
void setWeight(int_t vertex, int_t i, const wType &weight)
Sets the weight of the given edge.
Definition: digraph.h:685
void DFScolorStack(Table &tab, const Color &color, int_t vertex=0) const
A stack version of the recurrent procedure for DFScolor.
Definition: digraph.h:941
wType Johnson(const roundType &rounding, arrayType &arr, bool setInfinity=true, bool ignoreNegLoop=false) const
Runs Johnson's algorithm to compute the minimum path weight between any vertices in the graph.
Definition: digraph.h:2119
void DFScolorRecurrent(Table &tab, const Color &color, int_t vertex=0) const
The recurrent procedure for DFScolor.
Definition: digraph.h:925
void addVertex(void)
Adds a vertex.
Definition: digraph.h:641
void DFSfinishTimeRecurrent(Table &tab, int_t vertex, int_t &counter) const
The recurrent procedure for DFSfinishTime.
Definition: digraph.h:1011
bool BellmanFord(const roundType &rounding, int_t source, lenTable &len, wType *infinity, predTable pred) const
Runs the Bellman-Ford algorithm which computes the single-source shortest paths in a weighted directe...
Definition: digraph.h:1662
int_t getEdge(int_t vertex, int_t i) const
Retrieves the given edge that leaves the given vertex.
Definition: digraph.h:790
void transpose(diGraph< wType1 > &result, bool copyweights=false) const
Creates a transposed graph.
Definition: digraph.h:842
wType EdmondsOld() const
An old implementation of the Edmonds algorithm (less efficient).
Definition: digraph.h:1884
multitable< wType > weights
A table with edge weights.
Definition: digraph.h:466
int_t countEdges(void) const
Returns the number of edges.
Definition: digraph.h:772
A dummy array of integers that ignores all the assigned values.
Definition: digraph.h:117
dummyArray()
The constructor of a dummy array.
Definition: digraph.h:120
int_t & operator[](int_t)
Operator [] which returns a reference to a dummy value.
Definition: digraph.h:123
int_t n
A dummy number used as a dump box for assigning values.
Definition: digraph.h:127
A dummy class for rounding operations which does not actually do any rounding.
Definition: digraph.h:69
static numType mul_down(const numType &x, const numType &y)
Multiplies two numbers with the result rounded downwards.
Definition: digraph.h:88
static numType div_up(const numType &x, const numType &y)
Divides two numbers with the result rounded upwards.
Definition: digraph.h:104
static numType div_down(const numType &x, int_t y)
Divides a number by an integer with the result rounded downwards.
Definition: digraph.h:100
static numType add_down(const numType &x, const numType &y)
Adds two numbers with the result rounded downwards.
Definition: digraph.h:72
static numType sub_down(const numType &x, const numType &y)
Subtracts two numbers with the result rounded downwards.
Definition: digraph.h:80
static numType sub_up(const numType &x, const numType &y)
Subtracts two numbers with the result rounded upwards.
Definition: digraph.h:84
static numType add_up(const numType &x, const numType &y)
Adds two numbers with the result rounded upwards.
Definition: digraph.h:76
static numType mul_up(const numType &x, const numType &y)
Multiplies two numbers with the result rounded upwards.
Definition: digraph.h:92
static numType div_down(const numType &x, const numType &y)
Divides two numbers with the result rounded downwards.
Definition: digraph.h:96
This class defines a simple data structure for a flat 2-dim square matrix whose entries are stored in...
Definition: flatmatr.h:55
A class that stores the time at which it was initialized and then returns or displays the time used s...
Definition: timeused.h:67
This file contains the definition of a Fibonacci heap optimized for good memory usage.
This file contains the definition of a simple matrix class which is stored in a single vector,...
int int_t
Index type for indexing arrays, counting cubes, etc.
Definition: config.h:115
This file contains the definition of the container "hashedset" which can be used to represent a set o...
This file contains the definition of the container "multitable" which is essentially an automatically...
int_t computePeriod(const GraphType &g)
Computes the period of a strongly connected graph.
Definition: digraph.h:3879
int_t inclusionGraph(const diGraph< wType > &g, int_t nVert, diGraph< wType > &result)
Computes the graph that represents flow-induced relations on Morse sets.
Definition: digraph.h:3976
void graph2matrix(const diGraph< wType > &g, matrix &m)
Creates the adjacency matrix of the given graph.
Definition: digraph.h:4318
void transitiveReduction(matrix &m, int_t n)
Computes the transitive reduction of a CLOSED acyclic graph defined by its adjacency matrix,...
Definition: digraph.h:4380
void matrix2graph(const matrix &m, int_t n, diGraph< wType > &g)
Creates a graph based on the given adjacency matrix.
Definition: digraph.h:4338
std::ostream & operator<<(std::ostream &out, const bincube< Dim, twoPower > &b)
Definition: bincube.h:907
outputstream sbug
An output stream for writing additional debug messages.
int_t collapseVertices(const diGraph< wType > &g, int_t compNum, Table1 &compVertices, Table2 &compEnds, diGraph< wType > &result, int_t *newNumbers=0)
Collapses disjoint subsets of vertices to single vertices and creates a corresponding graph in which ...
Definition: digraph.h:3530
int_t addRenumEdges2(const diGraph< wType > &g, int_t vertex, const int_t *newNum, TabSets &numSets, int_t cur, int_t *srcVert, diGraph< wType > &result)
A helper function for "collapseVertices2".
Definition: digraph.h:3613
int_t connectionGraph(const diGraph< wType > &g, int_t nVert, diGraph< wType > &result)
Computes the graph that represents connections between a number of the first vertices in the given gr...
Definition: digraph.h:3769
void transitiveClosure(matrix &m, int_t n)
Computes the transitive closure of an acyclic graph defined by its adjacency matrix,...
Definition: digraph.h:4356
int_t collapseVertices2(const diGraph< wType > &g, int_t compNum, Table1 &compVertices, Table2 &compEnds, diGraph< wType > &result)
Collapses (possibly non-disjoint) subsets of vertices to single vertices and creates a corresponding ...
Definition: digraph.h:3656
bool operator!=(const typename bincube< Dim, twoPower >::neighborhood_iterator &x1, const typename bincube< Dim, twoPower >::neighborhood_iterator &x2)
Definition: bincube.h:794
int_t addRenumEdges(const diGraph< wType > &g, int_t vertex, const int_t *newNum, int_t cur, int_t *srcVert, diGraph< wType > &result)
A helper function for "collapseVertices".
Definition: digraph.h:3498
bool operator==(const typename bincube< Dim, twoPower >::neighborhood_iterator &x1, const typename bincube< Dim, twoPower >::neighborhood_iterator &x2)
Definition: bincube.h:785
int_t SCC_Tarjan(const diGraph< wType > &g, Table1 &compVertices, Table2 &compEnds)
Computes strongly connected components of the graph 'g' using Tarjan's algorithm (as described in the...
Definition: digraph.h:2434
int_t SCC(const diGraph< wType > &g, Table1 &compVertices, Table2 &compEnds, diGraph< wType > *scc=0, diGraph< wType > *transposed=0, bool copyweights=false)
Computes strongly connected components of the graph 'g'.
Definition: digraph.h:2392
void swap(mwWorkerData &data1, mwWorkerData &data2)
Definition: mwcoord.h:108
This namespace contains the entire CHomP library interface.
Definition: bitmaps.h:51
A helper class for ignoring predecessor information.
Definition: digraph.h:3288
void add(int_t, int_t, int_t)
Definition: digraph.h:3290
An edge with a weight (used by the Edmonds algorithm).
Definition: digraph.h:496
wType weight
The weight of the edge.
Definition: digraph.h:502
int_t vert1
The starting and ending vertices of the edge.
Definition: digraph.h:498
friend bool operator<(const edgeTriple &x, const edgeTriple &y)
The < operator for comparing the weights of edges.
Definition: digraph.h:505
This file contains some useful functions related to the text input/output procedures.
This file defines a simple data structure which can be used to measure time used by the program (or s...