Skip to content

Commit 817c3fc

Browse files
committed
adding test cases
1 parent 45ba45c commit 817c3fc

File tree

8 files changed

+150
-26
lines changed

8 files changed

+150
-26
lines changed

include/maxplus/base/analysis/mcm/mcmdg.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@
1414
* Function : Compute the MCM for a graph using Dasdan-Gupta's
1515
* algorithm.
1616
*
17+
* @article{Dasdan1998FasterMA,
18+
* title={Faster maximum and minimum mean cycle algorithms for system-performance analysis},
19+
* author={Ali Dasdan and Rajesh K. Gupta},
20+
* journal={IEEE Trans. Comput. Aided Des. Integr. Circuits Syst.},
21+
* year={1998},
22+
* volume={17},
23+
* pages={889-899}
24+
* }
25+
*
1726
* History :
1827
* 08-11-05 : Initial version.
1928
*
@@ -48,9 +57,10 @@ namespace Graphs {
4857

4958
/**
5059
* mcmDG ()
51-
* The function computes the maximum cycle mean of a HSDF graph using
60+
* The function computes the maximum cycle mean of an MCM graph using
5261
* Dasdan-Gupta's algorithm.
5362
* Note: this algorithm assumes that edge weights are integer valued !
63+
*
5464
* @todo
5565
* check if algorithm can be generalized to float edge weights
5666
*/

include/maxplus/base/analysis/mcm/mcmgraph.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class MCMgraph {
105105
MCMgraph &operator=(MCMgraph &&) = delete;
106106
MCMgraph &operator=(const MCMgraph &other) = delete;
107107

108+
[[nodiscard]] unsigned int numberOfNodes() { return static_cast<unsigned int>(this->nodes.size()); };
108109
[[nodiscard]] MCMnodes &getNodes() { return nodes; };
109110
[[nodiscard]] MCMnodeRefs getNodeRefs();
110111
[[nodiscard]] MCMedgeRefs getEdgeRefs();
@@ -127,6 +128,7 @@ class MCMgraph {
127128
return nullptr;
128129
};
129130

131+
[[nodiscard]] unsigned int numberOfEdges() { return static_cast<unsigned int>(this->edges.size()); };
130132
[[nodiscard]] MCMedges &getEdges() { return edges; };
131133

132134
MCMedge *getEdge(CId id) {
@@ -196,7 +198,7 @@ class MCMgraph {
196198
e.dst->in.remove(&e);
197199
}
198200

199-
void relabelNodeIds(std::map<int, int> &nodeIdMap);
201+
void relabelNodeIds(std::map<int, int> *nodeIdMap = nullptr);
200202

201203
// reduce the MCM graph by removing obviously redundant edges
202204
// in particular if there are multiple edges between the same pair

include/maxplus/base/analysis/mcm/mcmhoward.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,5 +88,8 @@ void Howard(const std::vector<int> &ij,
8888
int *nr_iterations,
8989
int *nr_components);
9090

91+
CDouble maximumCycleMeanHoward(MCMgraph &g, MCMnode **criticalNode);
92+
93+
9194
} // namespace Graphs
9295
#endif

src/algebra/mpmatrix.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1090,7 +1090,7 @@ Matrix::mp_generalized_eigenvectors() const {
10901090

10911091
// MCM calculation requires node relabelling
10921092
std::map<int, int> sccNodeIdMap;
1093-
scc->relabelNodeIds(sccNodeIdMap);
1093+
scc->relabelNodeIds(&sccNodeIdMap);
10941094

10951095
if (scc->nrVisibleEdges() > 0) {
10961096
// compute MCM mu and critical node n of scc

src/base/analysis/mcm/mcmdg.cc

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@
1414
* Function : Compute the MCM for an HSDF graph using Dasdan-Gupta's
1515
* algorithm.
1616
*
17+
* @article{Dasdan1998FasterMA,
18+
* title={Faster maximum and minimum mean cycle algorithms for system-performance analysis},
19+
* author={Ali Dasdan and Rajesh K. Gupta},
20+
* journal={IEEE Trans. Comput. Aided Des. Integr. Circuits Syst.},
21+
* year={1998},
22+
* volume={17},
23+
* pages={889-899}
24+
* }
25+
*
1726
* History :
1827
* 08-11-05 : Initial version.
1928
*
@@ -46,15 +55,11 @@
4655
#include <memory>
4756

4857
namespace Graphs {
49-
/**
50-
* mcmDG ()
51-
* The function computes the maximum cycle mean of a HSDF graph using
52-
* Dasdan-Gupta's algorithm.
53-
* Note: this algorithm assumes that edge weights are integer valued !
54-
* @todo
55-
* check if algorithm can be generalized to float edge weights
56-
*/
57-
CDouble mcmDG(MCMgraph &mcmGraph) {
58+
59+
// assumes teh graph is strongly connected and assumes the node ids are 0...N-1,
60+
// where N is the number of nodes
61+
CDouble mcmDG_SCC(MCMgraph &mcmGraph) {
62+
5863
// Allocate memory
5964
const int n = mcmGraph.nrVisibleNodes();
6065
std::vector<int> level(n);
@@ -70,17 +75,17 @@ CDouble mcmDG(MCMgraph &mcmGraph) {
7075
level[0] = 0;
7176
std::list<int> Q_k;
7277
Q_k.push_back(0);
73-
std::list<MCMnode*> Q_u;
78+
std::list<MCMnode *> Q_u;
7479
Q_u.push_back(&(mcmGraph.getNodes().front()));
7580

7681
// Compute the distances
7782
int k = Q_k.front();
7883
Q_k.pop_front();
79-
MCMnode* u = Q_u.front();
84+
MCMnode *u = Q_u.front();
8085
Q_u.pop_front();
8186
do {
82-
for (auto& e: u->out) {
83-
MCMnode* v = e->dst;
87+
for (auto &e : u->out) {
88+
MCMnode *v = e->dst;
8489

8590
if (level[v->id] < static_cast<int>(k + 1)) {
8691
Q_k.push_back(k + 1);
@@ -99,7 +104,7 @@ CDouble mcmDG(MCMgraph &mcmGraph) {
99104

100105
// Compute lambda using Karp's theorem
101106
CDouble l = -INT_MAX;
102-
for (const auto & u : mcmGraph.getNodes()) {
107+
for (const auto &u : mcmGraph.getNodes()) {
103108

104109
if (level[u.id] == n) {
105110
CDouble ld = INT_MAX;
@@ -114,5 +119,31 @@ CDouble mcmDG(MCMgraph &mcmGraph) {
114119

115120
return l;
116121
}
122+
123+
124+
/**
125+
* mcmDG ()
126+
* The function computes the maximum cycle mean of an MCM graph using
127+
* Dasdan-Gupta's algorithm.
128+
* Note: this algorithm assumes that edge weights are integer valued !
129+
* @todo
130+
* check if algorithm can be generalized to float edge weights
131+
*/
132+
CDouble mcmDG(MCMgraph &mcmGraph) {
133+
134+
MCMgraphs sccs;
135+
stronglyConnectedMCMgraph(mcmGraph, sccs, false);
136+
137+
CDouble mcm = -INFINITY;
138+
for (auto &scc : sccs) {
139+
scc->relabelNodeIds();
140+
CDouble cmcm = mcmDG_SCC(*scc);
141+
if (cmcm > mcm) {
142+
mcm = cmcm;
143+
}
144+
}
145+
146+
return mcm;
147+
}
117148

118149
} // namespace Graphs

src/base/analysis/mcm/mcmgraph.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -755,11 +755,13 @@ CDouble MCMgraph::calculateMaximumCycleRatioAndCriticalCycleYoungTarjanOrlin(
755755
return maxCycleRatioAndCriticalCycleYoungTarjanOrlin(*this, cycle);
756756
}
757757

758-
void MCMgraph::relabelNodeIds(std::map<int, int> &nodeIdMap) {
758+
void MCMgraph::relabelNodeIds(std::map<int, int> *nodeIdMap) {
759759
int k = 0;
760760
for (auto &i : this->nodes) {
761761
MCMnode &n = i;
762-
nodeIdMap[k] = static_cast<int>(n.id);
762+
if (nodeIdMap != nullptr) {
763+
(*nodeIdMap)[k] = static_cast<int>(n.id);
764+
}
763765
n.id = k;
764766
k++;
765767
}

src/base/analysis/mcm/mcmhoward.cc

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,4 +514,54 @@ void convertMCMgraphToMatrix(MCMgraph &g,
514514
}
515515
}
516516
}
517+
518+
CDouble maximumCycleMeanHoward(MCMgraph& g, MCMnode* *criticalNode) {
519+
520+
if (g.numberOfNodes() == 0) {
521+
if (criticalNode != nullptr) {
522+
(*criticalNode) = nullptr;
523+
}
524+
return -INFINITY;
525+
}
526+
527+
std::shared_ptr<std::vector<int>> ij = nullptr;
528+
std::shared_ptr<std::vector<CDouble>> A = nullptr;
529+
std::shared_ptr<std::vector<CDouble>> chi = nullptr;
530+
std::shared_ptr<std::vector<CDouble>> v = nullptr;
531+
std::shared_ptr<std::vector<int>> policy = nullptr;
532+
int nr_iterations = 0;
533+
int nr_components = 0;
534+
535+
convertMCMgraphToMatrix(g, &ij, &A);
536+
537+
Howard(*ij,
538+
*A,
539+
g.numberOfNodes(),
540+
g.numberOfEdges(),
541+
&chi,
542+
&v,
543+
&policy,
544+
&nr_iterations,
545+
&nr_components);
546+
547+
// find maximum cycle mean in chi vector
548+
MCMnodes& nodes = g.getNodes();
549+
auto &n = nodes.begin();
550+
CDouble mcm = chi->at(0);
551+
MCMnode *critNode = &(*n);
552+
for (auto &val : *chi) {
553+
if (val > mcm) {
554+
mcm = val;
555+
critNode = &(*n);
556+
n++;
557+
}
558+
}
559+
560+
if (criticalNode != nullptr) {
561+
(*criticalNode) = &(*n);
562+
}
563+
return mcm;
564+
}
565+
566+
517567
} // namespace Graphs

src/testbench/base/mcmtest.cc

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,35 @@ MCMgraph makeGraph1() {
3838
return g;
3939
}
4040

41+
// A corner case graph
42+
MCMgraph makeGraph2() {
43+
MCMgraph g;
44+
45+
MCMnode &n0 = *g.addNode(0);
46+
MCMnode &n1 = *g.addNode(1);
47+
g.addEdge(0, n0, n1, 1.0, 1.0);
48+
//g.addEdge(1, n1, n1, 1.0, 1.0);
49+
return g;
50+
}
51+
52+
4153
// Test mcmdg.
4254
void MCMTest::test_dg() {
4355
std::cout << "Running test: MCM-dg" << std::endl;
4456

45-
MCMgraph g = makeGraph1();
46-
CDouble result = mcmDG(g);
57+
MCMgraph g1 = makeGraph1();
58+
CDouble result = mcmDG(g1);
4759
ASSERT_APPROX_EQUAL(2.5, result, 1e-5);
60+
61+
MCMgraph g2 = makeGraph2();
62+
result = mcmDG(g2);
63+
ASSERT_EQUAL(-INFINITY, result);
4864
}
4965

5066
/// Test MCM Howard.
5167
void MCMTest::test_howard() {
5268
std::cout << "Running test: MCM-Howard" << std::endl;
53-
MCMgraph g = makeGraph1();
69+
MCMgraph g1 = makeGraph1();
5470

5571
std::shared_ptr<std::vector<int>> ij = nullptr;
5672
std::shared_ptr<std::vector<CDouble>> A = nullptr;
@@ -60,12 +76,12 @@ void MCMTest::test_howard() {
6076
int nr_iterations = 0;
6177
int nr_components = 0;
6278

63-
convertMCMgraphToMatrix(g, &ij, &A);
79+
convertMCMgraphToMatrix(g1, &ij, &A);
6480

65-
Howard(*ij,
81+
Howard(*ij,
6682
*A,
67-
static_cast<int>(g.getNodes().size()),
68-
static_cast<int>(g.getEdges().size()),
83+
static_cast<int>(g1.getNodes().size()),
84+
static_cast<int>(g1.getEdges().size()),
6985
&chi,
7086
&v,
7187
&policy,
@@ -83,6 +99,16 @@ void MCMTest::test_howard() {
8399
ASSERT_EQUAL(3, policy->at(2));
84100
ASSERT_EQUAL(0, policy->at(3));
85101
ASSERT_EQUAL(4, policy->at(4));
102+
103+
MCMnode *criticalNode;
104+
CDouble result = maximumCycleMeanHoward(g1, &criticalNode);
105+
ASSERT_APPROX_EQUAL(2.5, result, 1e-5);
106+
ASSERT_THROW(criticalNode->id == 0 || criticalNode->id == 1 || criticalNode->id == 2
107+
|| criticalNode->id == 3);
108+
109+
MCMgraph g2 = makeGraph2();
110+
result = maximumCycleMeanHoward(g2, &criticalNode);
111+
ASSERT_EQUAL(-INFINITY, result);
86112
}
87113

88114
/// Test MCM Karp.

0 commit comments

Comments
 (0)