1 | ///Generates a random graph, and tests max_matching.h on it. |
---|
2 | #include <iostream> |
---|
3 | #include <queue> |
---|
4 | #include <math.h> |
---|
5 | |
---|
6 | #include <list_graph.h> |
---|
7 | #include <dimacs.h> |
---|
8 | #include <graph_gen.h> |
---|
9 | #include <max_matching.h> |
---|
10 | #include <time_measure.h> |
---|
11 | #include <graph_wrapper.h> |
---|
12 | |
---|
13 | using namespace hugo; |
---|
14 | |
---|
15 | int main(int, char **) { |
---|
16 | |
---|
17 | typedef UndirGraph<ListGraph> UGW; |
---|
18 | typedef UGW::Edge Edge; |
---|
19 | typedef UGW::EdgeIt EdgeIt; |
---|
20 | typedef UGW::OutEdgeIt OutEdgeIt; |
---|
21 | typedef UGW::NodeIt NodeIt; |
---|
22 | typedef UGW::Node Node; |
---|
23 | |
---|
24 | UGW G; |
---|
25 | |
---|
26 | // random_init(); //If you want to use a random graph with a random |
---|
27 | // number of edges and nodes. |
---|
28 | |
---|
29 | int i; |
---|
30 | int j; |
---|
31 | std::cout<<"Number of nodes: "; |
---|
32 | std::cin >> i; |
---|
33 | std::cout<<"Number of edges: "; |
---|
34 | std::cin >> j; |
---|
35 | |
---|
36 | // readDimacs(std::cin, G); |
---|
37 | randomGraph(G, i, j ); |
---|
38 | |
---|
39 | Timer ts; |
---|
40 | bool noerror=true; |
---|
41 | |
---|
42 | std::cout << |
---|
43 | "\n Testing max_matching.h on a random graph with " << |
---|
44 | G.nodeNum() << " nodes and " << G.edgeNum() << " edges...\n" |
---|
45 | << std::endl; |
---|
46 | MaxMatching<UGW> max_matching(G); |
---|
47 | |
---|
48 | |
---|
49 | std::cout << |
---|
50 | "Running the plain edmonds algorithm runEdmonds(0) using no heuristic... " |
---|
51 | <<std::endl; |
---|
52 | ts.reset(); |
---|
53 | max_matching.runEdmonds(0); |
---|
54 | std::cout<<"Elapsed time: "<<ts<<std::endl; |
---|
55 | int s=0; |
---|
56 | UGW::NodeMap<Node> mate(G,INVALID); |
---|
57 | max_matching.writeNMapNode(mate); |
---|
58 | NodeIt v; |
---|
59 | for(G.first(v); G.valid(v); G.next(v) ) { |
---|
60 | if ( G.valid(mate[v]) ) { |
---|
61 | ++s; |
---|
62 | } |
---|
63 | } |
---|
64 | int size=(int)s/2; //size will be used as the size of a maxmatching |
---|
65 | std::cout << size << " is the size of the matching found by runEdmonds(0),"<<std::endl; |
---|
66 | if ( size == max_matching.size() ) { |
---|
67 | std::cout<< "which equals to the size of the actual matching reported by size().\n"<< std::endl; |
---|
68 | } else { |
---|
69 | std::cout<< "which does not equal to the size of the actual matching reported by size()!\n"<< std::endl; |
---|
70 | noerror=false; |
---|
71 | } |
---|
72 | |
---|
73 | |
---|
74 | std::cout<<"Writing the position by calling writePos..."; |
---|
75 | UGW::NodeMap<MaxMatching<UGW>::pos_enum> pos0(G); |
---|
76 | max_matching.writePos(pos0); |
---|
77 | std::cout << "OK" << std::endl; |
---|
78 | |
---|
79 | |
---|
80 | std::cout << "Resetting the matching and the position by calling"<< std::endl; |
---|
81 | std::cout<<"resetPos() and resetMatching()..."; |
---|
82 | max_matching.resetPos(); |
---|
83 | max_matching.resetMatching(); |
---|
84 | std::cout <<"OK" << std::endl; |
---|
85 | |
---|
86 | |
---|
87 | std::cout << "\nRunning runEdmonds(1) using the 'postpone shrink' heuristic ... " <<std::endl; |
---|
88 | ts.reset(); |
---|
89 | max_matching.runEdmonds(1); |
---|
90 | std::cout<<"Elapsed time: "<<ts<<std::endl; |
---|
91 | s=0; |
---|
92 | max_matching.writeNMapNode(mate); |
---|
93 | for(G.first(v); G.valid(v); G.next(v) ) { |
---|
94 | if ( G.valid(mate[v]) ) { |
---|
95 | ++s; |
---|
96 | } |
---|
97 | } |
---|
98 | std::cout << (int)s/2 << |
---|
99 | " is the size of the matching found by runEdmonds(1),"<<std::endl; |
---|
100 | if ( (int)s/2 == size ) { |
---|
101 | std::cout<< "which equals to the size of the matching found by runEdmonds(0)."<< std::endl; |
---|
102 | } else { |
---|
103 | std::cout<< "which does not equal to the size of the matching found by runEdmonds(0)!"<< std::endl; |
---|
104 | noerror=false; |
---|
105 | } |
---|
106 | UGW::NodeMap<MaxMatching<UGW>::pos_enum> pos1(G); |
---|
107 | max_matching.writePos(pos1); |
---|
108 | |
---|
109 | |
---|
110 | std::cout << "\nStarting run() from the matching given by runEdmonds(1)... " <<std::endl; |
---|
111 | max_matching.resetPos(); |
---|
112 | ts.reset(); |
---|
113 | max_matching.run(); |
---|
114 | std::cout<<"Elapsed time: "<<ts<<std::endl; |
---|
115 | s=0; |
---|
116 | max_matching.writeNMapNode(mate); |
---|
117 | for(G.first(v); G.valid(v); G.next(v) ) { |
---|
118 | if ( G.valid(mate[v]) ) { |
---|
119 | ++s; |
---|
120 | } |
---|
121 | } |
---|
122 | if ( (int)s/2 == size ) { |
---|
123 | std::cout<< "Found a matching of proper size."<< std::endl; |
---|
124 | } else { |
---|
125 | std::cout<< "Found a matching of inproper size!"<< std::endl; |
---|
126 | noerror=false; |
---|
127 | } |
---|
128 | UGW::NodeMap<MaxMatching<UGW>::pos_enum> pos2(G); |
---|
129 | max_matching.writePos(pos2); |
---|
130 | |
---|
131 | |
---|
132 | std::cout << "\nCalling resetPos() and resetMatching()..."; |
---|
133 | max_matching.resetPos(); |
---|
134 | max_matching.resetMatching(); |
---|
135 | std::cout<<"OK"<<std::endl; |
---|
136 | std::cout <<"Calling greedyMatching() and then runEdmonds(1)... " <<std::endl; |
---|
137 | ts.reset(); |
---|
138 | max_matching.run(); |
---|
139 | std::cout<<"Elapsed time: "<<ts<<std::endl; |
---|
140 | s=0; |
---|
141 | max_matching.writeNMapNode(mate); |
---|
142 | for(G.first(v); G.valid(v); G.next(v) ) { |
---|
143 | if ( G.valid(mate[v]) ) { |
---|
144 | ++s; |
---|
145 | } |
---|
146 | } |
---|
147 | std::cout << (int)s/2 << " is the size of the matching found by run(),"<<std::endl; |
---|
148 | if ( (int)s/2 == size ) { |
---|
149 | std::cout<< "which equals to the size of the matching found by runEdmonds(0)."<< std::endl; |
---|
150 | } else { |
---|
151 | std::cout<< "which does not equal to the size of the matching found by runEdmonds(0)!"<< std::endl; |
---|
152 | noerror=false; |
---|
153 | } |
---|
154 | UGW::NodeMap<MaxMatching<UGW>::pos_enum> pos(G); |
---|
155 | max_matching.writePos(pos); |
---|
156 | |
---|
157 | |
---|
158 | std::cout<<"\nChecking if the output is a matching..."; |
---|
159 | bool ismatching=true; |
---|
160 | for(G.first(v); G.valid(v); G.next(v) ) |
---|
161 | if ( G.valid(mate[v]) ) { |
---|
162 | Node u=mate[v]; |
---|
163 | if (mate[u]!=v) ismatching=false; |
---|
164 | } |
---|
165 | if ( ismatching ) std::cout<<"OK"<<std::endl; |
---|
166 | else std::cout<< "It is not a matching!"<< std::endl; |
---|
167 | noerror = noerror && ismatching; |
---|
168 | |
---|
169 | |
---|
170 | std::cout<<"\nChecking the dual..."<<std::endl; |
---|
171 | |
---|
172 | std::cout<<"Checking if the four position outputs coincide..."; |
---|
173 | bool coincide=true; |
---|
174 | int err_node=0; |
---|
175 | for(G.first(v); G.valid(v); G.next(v) ) { |
---|
176 | if ( pos0[v] != pos1[v] || pos1[v]!=pos2[v] || pos2[v]!=pos[v] ) { |
---|
177 | ++err_node; |
---|
178 | coincide=false; |
---|
179 | } |
---|
180 | } |
---|
181 | if ( coincide ) std::cout << "OK" <<std::endl; |
---|
182 | else { |
---|
183 | std::cout << "They do not coincide! Number of erroneous nodes: " |
---|
184 | << err_node << std::endl; |
---|
185 | } |
---|
186 | noerror=noerror && coincide; |
---|
187 | |
---|
188 | |
---|
189 | std::cout<<"Checking if there is no edge between D and C..."; |
---|
190 | bool noedge=true; |
---|
191 | EdgeIt e; |
---|
192 | for(G.first(e); G.valid(e); G.next(e) ) { |
---|
193 | if ( (pos[G.head(e)]==max_matching.C && pos[G.tail(e)]==max_matching.D) || |
---|
194 | (pos[G.head(e)]==max_matching.D && pos[G.tail(e)]==max_matching.C) ) |
---|
195 | noedge=false; |
---|
196 | } |
---|
197 | if ( noedge ) std::cout<<"OK"<<std::endl; |
---|
198 | else std::cout<< "There are edges between D and C!"<< std::endl; |
---|
199 | noerror = noerror && noedge; |
---|
200 | |
---|
201 | |
---|
202 | std::cout<<"Checking if all the components of G[D] are odd..."; |
---|
203 | bool oddcomp=true; |
---|
204 | UGW::NodeMap<bool> todo(G,true); |
---|
205 | int num_comp=0; |
---|
206 | for(G.first(v); G.valid(v); G.next(v) ) { |
---|
207 | if ( pos[v]==max_matching.D && todo[v] ) { |
---|
208 | int comp_size=1; |
---|
209 | ++num_comp; |
---|
210 | std::queue<Node> Q; |
---|
211 | Q.push(v); |
---|
212 | todo.set(v,false); |
---|
213 | while (!Q.empty()) { |
---|
214 | Node w=Q.front(); |
---|
215 | Q.pop(); |
---|
216 | OutEdgeIt e; |
---|
217 | for(G.first(e,w); G.valid(e); G.next(e)) { |
---|
218 | Node u=G.bNode(e); |
---|
219 | if ( pos[u]==max_matching.D && todo[u] ) { |
---|
220 | ++comp_size; |
---|
221 | Q.push(u); |
---|
222 | todo.set(u,false); |
---|
223 | } |
---|
224 | } |
---|
225 | } |
---|
226 | if ( !(comp_size % 2) ) oddcomp=false; |
---|
227 | } |
---|
228 | } |
---|
229 | std::cout << "\n found " << num_comp << " component(s) of G[D],"; |
---|
230 | if ( oddcomp ) std::cout<<" each is odd."<<std::endl; |
---|
231 | else std::cout<< " but not all are odd!"<< std::endl; |
---|
232 | noerror = noerror && oddcomp; |
---|
233 | |
---|
234 | |
---|
235 | int barrier=0; |
---|
236 | for(G.first(v); G.valid(v); G.next(v) ) |
---|
237 | if ( pos[v]==max_matching.A ) ++barrier; |
---|
238 | std::cout << barrier << " is the number of nodes in A (i.e. the size of the barrier), so" << std::endl; |
---|
239 | std::cout << num_comp - barrier << " is the deficiency of the graph, and hence" << std::endl; |
---|
240 | int expected_size=(int)(G.nodeNum()-num_comp+barrier)/2; |
---|
241 | std::cout << expected_size << " should be the size of the maximum matching," << std::endl; |
---|
242 | if ( size==expected_size ) |
---|
243 | std::cout<<"which equals to the number of vertices missed by the found matching!"<<std::endl; |
---|
244 | else { |
---|
245 | std::cout<<"which does not equal to the number of vertices missed by the matchings found!" |
---|
246 | <<std::endl; |
---|
247 | noerror=false; |
---|
248 | } |
---|
249 | |
---|
250 | |
---|
251 | if ( num_comp == 1 && barrier == 0 ) |
---|
252 | std::cout<<"\nThis graph is factor-critical."<<std::endl; |
---|
253 | if ( num_comp == 0 && barrier == 0 ) |
---|
254 | std::cout<<"\nThis graph has a perfect matching."<<std::endl; |
---|
255 | |
---|
256 | |
---|
257 | if( noerror ) std::cout<<"\nNo errors found.\n"<<std::endl; |
---|
258 | else std::cout<<"\nSome errors found!\n"<<std::endl; |
---|
259 | |
---|
260 | return 0; |
---|
261 | } |
---|
262 | |
---|
263 | |
---|
264 | |
---|
265 | |
---|
266 | |
---|
267 | |
---|
268 | |
---|
269 | |
---|
270 | |
---|