2
* Copyright (c) 2008 Mellanox Technologies LTD. All rights reserved.
4
* This software is available to you under a choice of one of two
5
* licenses. You may choose to be licensed under the terms of the GNU
6
* General Public License (GPL) Version 2, available from the file
7
* COPYING in the main directory of this source tree, or the
8
* OpenIB.org BSD license below:
10
* Redistribution and use in source and binary forms, with or
11
* without modification, are permitted provided that the following
14
* - Redistributions of source code must retain the above
15
* copyright notice, this list of conditions and the following
18
* - Redistributions in binary form must reproduce the above
19
* copyright notice, this list of conditions and the following
20
* disclaimer in the documentation and/or other materials
21
* provided with the distribution.
23
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35
#include "Bipartite.h"
37
//CLASS edge///////////////////////////////////
39
bool edge::isMatched() {
40
vertex* ver1 = (vertex*)v1;
41
vertex* ver2 = (vertex*)v2;
43
if (((this == ver1->getPartner()) && (this != ver2->getPartner())) || ((this == ver2->getPartner()) && (this != ver1->getPartner())))
44
cout << "-E- Error in edge matching" << endl;
46
return (this == ver1->getPartner()) && (this == ver2->getPartner());
49
//CLASS vertex/////////////////////////////////
51
vertex::vertex(int n, side sd, int rad):id(n),s(sd),radix(rad)
53
connections = new edge*[radix];
54
pred = new edge*[radix];
55
succ = new edge*[radix];
58
for (int i=0; i<radix; i++)
59
connections[i] = pred[i] = succ[i] = NULL;
61
predCount = succCount = 0;
72
int vertex::getID() const
77
side vertex::getSide() const
82
void vertex::delConnection(edge* e)
84
int my_idx, other_idx;
87
// Find the side we are connected at and edge index
93
else if (e->v2 == this) {
99
cout << "-E- Edge not connected to current vertex" << endl;
103
if (my_idx >= radix || other_idx >= radix) {
104
cout << "-E- Edge index illegal" << endl;
109
connections[my_idx] = NULL;
111
v->connections[other_idx] = NULL;
115
void vertex::pushConnection(edge* e)
118
if (maxUsed == radix) {
119
cout << "-E- Can't push connection to vertex: " << id << ", exceeding radix!" << endl;
127
else if (e->v2 == NULL) {
132
cout << "-E- Can't push connection both edges are already filled" << endl;
136
if (maxUsed >= radix) {
137
cout << "-E- maxUsed illegal" << endl;
142
connections[maxUsed] = e;
145
edge* vertex::popConnection()
147
// Look for a connection
149
while ((i<radix) && !connections[i])
151
// No real connection found
155
edge* tmp = connections[i];
157
// Disconnect chosen edge
158
connections[i] = NULL;
159
if (tmp->v1 == this) {
160
vertex* v = (vertex*)(tmp->v2);
161
v->connections[tmp->idx2] = NULL;
163
else if (tmp->v2 == this) {
164
vertex* v = (vertex*)(tmp->v1);
165
v->connections[tmp->idx1] = NULL;
168
cout << "-E- Edge not connected to current vertex" << endl;
172
if (tmp->idx1 >= radix || tmp->idx2 >= radix) {
173
cout << "-E- Edge index illegal" << endl;
180
// For unmacthed vertex, find an unmatched neighbor and match the pair
187
for (int i=0; i<radix; i++) {
188
if (connections[i]) {
189
vertex* v = (vertex*)(connections[i]->otherSide(this));
192
partner = connections[i];
193
v->partner = connections[i];
201
edge* vertex::getPartner() const
206
bool vertex::getInLayers() const
211
void vertex::setInLayers(bool b)
216
void vertex::resetLayersInfo()
219
succCount = predCount = 0;
220
for (int i=0; i<radix; i++)
221
succ[i] = pred[i] = NULL;
224
void vertex::addPartnerLayers(list<vertex*>& l)
229
vertex* p = (vertex*)(partner->otherSide(this));
230
// Partner already in one of the layers
233
// Add partner to the layer
236
// Update pred/succ relations
237
if (succCount >= radix) {
238
cout << "-E- More successors than radix" << endl;
241
succ[succCount] = partner;
244
if (p->predCount >= radix) {
245
cout << "-E- More predecessors than radix" << endl;
248
p->pred[p->predCount] = partner;
252
bool vertex::addNonPartnersLayers(list<vertex*>& l)
258
prtn = (vertex*)(partner->otherSide(this));
260
for (int i=0; i<radix; i++) {
261
vertex* v = (vertex*)(connections[i]->otherSide(this));
262
if ((v != prtn) && (!v->inLayers)) {
266
// Add vertex to the layer
269
// Update pred/succ relations
270
if (succCount >= radix) {
271
cout << "-E- More successors than radix" << endl;
274
succ[succCount] = connections[i];
277
if (v->predCount >= radix) {
278
cout << "-E- More predecessors than radix" << endl;
281
v->pred[v->predCount] = connections[i];
288
vertex* vertex::getPredecessor() const
291
// Find a valid predecessor still in layers
292
for (int i=0; i<radix; i++) {
294
vertex* v2 = (vertex*)(pred[i]->otherSide(this));
304
// Flip edge status on augmenting path
305
void vertex::flipPredEdge(int idx)
308
// Find an edge to a predecessor
309
for (i=0; i<radix; i++)
311
vertex* v1 = (vertex*)pred[i]->v1;
312
vertex* v2 = (vertex*)pred[i]->v2;
313
if (v1->getInLayers() && v2->getInLayers())
318
cout << "-E- Could find predecessor for flip" << endl;
321
// The predecessor vertex
322
vertex* v = (vertex*) pred[i]->otherSide(this);
330
v->partner = pred[i];
334
// Removing vertex from layers and updating successors/predecessors
335
void vertex::unLink(list<vertex*>& l)
338
for (int i=0; i<radix; i++) {
340
vertex* v = (vertex*)succ[i]->otherSide(this);
343
// v has no more predecessors, schedule for removal from layers...
357
Bipartite::Bipartite(int s, int r):size(s),radix(r)
359
leftSide = new vertex*[size];
360
rightSide = new vertex*[size];
362
for (int i=0; i<size; i++) {
363
leftSide[i] = new vertex(i,LEFT,radix);
364
rightSide[i] = new vertex(i,RIGHT,radix);
368
///////////////////////////////////////////////////////////
372
Bipartite::~Bipartite()
375
for (int i=0; i<size; i++) {
383
while (List.size()) {
384
edge* e = (edge*)(List.front());
390
////////////////////////////////////////////////////////////
394
int Bipartite::getRadix() const
399
////////////////////////////////////////////////////////////
401
// Set edges listt iterator to first
403
bool Bipartite::setIterFirst()
406
if (it == List.end())
411
///////////////////////////////////////////////////////////
413
// Set edges list iterator to next
415
bool Bipartite::setIterNext()
417
if (it == List.end())
420
if (it == List.end())
425
////////////////////////////////////////////////////////////
427
// Get current edge's request data
429
inputData Bipartite::getReqDat()
431
if (it == List.end()) {
432
cout << "-E- Iterator points to list end" << endl;
434
return ((edge*)(*it))->reqDat;
437
/////////////////////////////////////////////////////////////
439
// Add connection between the nodes to the graph
441
void Bipartite::connectNodes(int n1, int n2, inputData reqDat)
443
if ((n1 >= size) || (n2 >= size)) {
444
cout << "-E- Node index exceeds size" << endl;
448
edge* newEdge = new edge;
450
// Init edge fields and add to it the edges list
451
newEdge->it = List.insert(List.end(), newEdge);
452
newEdge->reqDat = reqDat;
453
newEdge->v1 = newEdge->v2 = NULL;
455
// Connect the vertices
456
leftSide[n1]->pushConnection(newEdge);
457
rightSide[n2]->pushConnection(newEdge);
460
////////////////////////////////////////////////////////////////
462
// Find maximal matching
464
void Bipartite::maximalMatch()
466
// Invoke match on left-side vertices
467
for (int i=0; i<size; i++)
468
leftSide[i]->match();
471
////////////////////////////////////////////////////////////////
473
// Find maximum matching
475
// Hopcroft-Karp algorithm
476
Bipartite* Bipartite::maximumMatch()
478
// First find a maximal match
481
list<void*>::iterator it2 = List.begin();
482
list<vertex*> l1, l2;
483
list<vertex*>::iterator it;
485
// Loop on algorithm phases
487
bool hardStop = false;
488
// First reset layers info
489
for (int i=0; i<size; i++) {
490
leftSide[i]->resetLayersInfo();
491
rightSide[i]->resetLayersInfo();
493
// Add free left-side vertices to l1 (building layer 0)
495
for (int i=0; i<size; i++) {
496
if (!leftSide[i]->getPartner()) {
497
l1.push_front(leftSide[i]);
498
leftSide[i]->setInLayers(true);
501
// This is our termination condition
502
// Maximum matching achieved
505
// Loop on building layers
509
// Add all non-partners of vertices in l1 to layers (l2)
510
// We signal to stop if a free (right-side) vertex is entering l2
511
for (it = l1.begin(); it != l1.end(); it++)
512
if ((*it)->addNonPartnersLayers(l2))
514
// Found free vertex among right-side vertices
516
// There are augmenting paths, apply them
520
// This is a terminal condition
525
// Add partners of vertices in l2 to layers (l1)
527
for (it = l2.begin(); it!= l2.end(); it++)
528
(*it)->addPartnerLayers(l1);
529
// This is a terminal condition
535
// Maximum matching achieved
539
// Build the matching graph
540
Bipartite* M = new Bipartite(size, 1);
541
// Go over all edges and move matched one to the new graph
543
while (it2 != List.end()) {
544
edge* e = (edge*)(*it2);
545
if (e->isMatched()) {
546
vertex* v1 = (vertex*)(e->v1);
547
vertex* v2 = (vertex*)(e->v2);
549
((vertex*)(e->v1))->delConnection(e);
551
it2 = List.erase(it2);
552
// Add link to the new graph
553
if (v1->getSide() == LEFT)
554
M->connectNodes(v1->getID(), v2->getID(), e->reqDat);
556
M->connectNodes(v2->getID(), v1->getID(), e->reqDat);
566
//////////////////////////////////////////////////////////////////////
568
// Apply augmenting paths on the matching
570
void Bipartite::augment(list<vertex*>& l)
572
// Use delQ to store vertex scheduled for the removal from layers
574
// Remove non-free vertices
575
list<vertex*>::iterator it = l.begin();
576
while (it != l.end()) {
577
if ((*it)->getPartner()) {
578
delQ.push_front((*it));
584
// Get rid of non-free vertices
585
while (!delQ.empty()) {
586
vertex* fr = delQ.front();
592
cout << "-E- No free vertices left!" << endl;
595
// Augment and reset pred/succ relations
597
vertex* curr = l.front();
600
// Backtrace the path and augment
603
delQ.push_front(curr);
604
// Its either the end of a path or an error
605
if (!curr->getPredecessor()) {
606
if (!idx && length) {
607
cout << "-E- This vertex must have predecessor" << endl;
613
curr->flipPredEdge(idx);
615
curr = curr->getPredecessor();
619
// Now clean the delQ
620
while (!delQ.empty()) {
621
vertex* fr = delQ.front();
628
////////////////////////////////////////////////////////////////////////
630
// Perform Euler decomposition
632
void Bipartite::decompose(Bipartite** bp1, Bipartite** bp2)
635
cout << "-E- Radix value illegal: " << radix << endl;
641
arr[0] = new Bipartite(size, radix/2);
642
arr[1] = new Bipartite(size, radix/2);
644
// Continue as long as unassigned edges left
645
while (!List.empty()) {
647
edge* e = (edge*)List.front();
648
vertex* current = (vertex*)e->v1;
649
e = current->popConnection();
652
// Connect nodes in the new graphs
653
vertex* v1 = (vertex*)e->v1;
654
vertex* v2 = (vertex*)e->v2;
655
if (v1->getSide() == LEFT)
656
arr[idx]->connectNodes(v1->getID(), v2->getID(), e->reqDat);
658
arr[idx]->connectNodes(v2->getID(), v1->getID(), e->reqDat);
660
// Remove edge from list
663
current = (vertex*) e->otherSide(current);
667
e = current->popConnection();